\(\\\)php
對於兩個點\((x_1,y_1),(x_2,y_2)\),定義他們的曼哈頓距離爲\(|x_1-x_2|+|y_1-y_2|\),即兩座標軸分別討論差值再求和。ios
對於曼哈頓距離相同的點,他們分佈在同一橫縱截距且截距相同的直線上。c++
圖中每個正方形邊界上的整點到原點的曼哈頓距離相同。git
\(\\\)數組
對於兩個點\((x_1,y_1),(x_2,y_2)\),定義他們的曼哈頓距離爲\(max\{|x_1-x_2|,|y_1-y_2|\}\),即兩座標軸分別討論差值取最大。spa
對於切比雪夫距離相同的點,他們分佈在以原點爲中心的正方形邊界上。3d
圖中每個正方形邊界上的整點到原點的曼哈頓距離相同。code
\(\\\)blog
考慮曼哈頓距離的表達式:\(|x_1-x_2|+|y_1-y_2|\),其實能夠表示成:排序
\(\begin{align}max\{x_1-x_2+y_1-y_2,x_1-x_2+y_2-y_1,x_2-x_1+y_1-y_2,x_2-x_1+y_2-y_1\}\end{align}\)
考慮將兩個點變化爲\((x_1+y_1,x_1-y_1),(x_2+y_2,x_2-y_2)\)
那麼變化後兩點的切比雪夫距離爲\(max((|(x_1+y_1)-(x_2+y_2)|,|(x_1-y_1)-(x_2-y_2)|)\)
若原來兩點曼哈頓距離爲\(x_1-x_2+y_1-y_2\)或\(x_2-x_1+y_2-y_1\)時,均可以表示爲\(|(x_1+y_2)-(x_2+y_2)|\)
若原來兩點曼哈頓距離爲\(x_1-x_2+y_2-y_1\)或\(x_2-x_1+y_1-y_2\)時,均可以表示爲\(|(x_1-y_1)-(x_2-y_2)|\)
將每個點\((x,y)\)轉化爲\((x+y,x-y)\),新座標系下的切比雪夫距離即爲原座標系下曼哈頓距離。
\(\\\)
按照剛纔的思路再還原回去便可。
將每個點\((x,y)\)轉化爲\((\frac{x+y}{2},\frac{x-y}{2})\),新座標系下的曼哈頓距離即爲原座標系下切比雪夫距離。
這個轉化通常比較經常使用,曼哈頓距離通常能夠經過排序前綴和的方式下降計算複雜度。
注意到除法若是向下取整可能會使答案不正確,因此考慮先不除以\(2\),最後求完答案再除以\(2\)也是同樣的,形象的理解能夠說成,曼哈頓座標系是經過切比雪夫座標系旋轉\(45^{\circ}\)後,再縮小到原來的一半獲得的。
\(\\\)
有\(N\)個二位平面上的點,定義每個點到其八連通的點的距離爲\(1\)。
選一個點,使得剩下全部點到該點的距離之和最小,求出這個距離之和。
- \(N\in [0,10^5]\)
\(\\\)
題意即爲求切比雪夫距離之和最小,暴力的作法是\(N^2\)的。
考慮將切比雪夫距離轉化爲曼哈頓距離,咱們將橫縱座標分開排序求前綴和,這樣既可快速求出,以一個點爲中心,其餘點到這個點的曼哈頓距離之和。
具體的作法是將兩個座標分開討論,每次找到當前點在排序後數組的位置\(p\)。
那麼它前面的點座標都小於當前點,累加的答案爲\(p\times x[i]-sum_p\)。
後面的點的座標都大於當前點,反過來累加答案,爲\((sum_n-sum_p)-(n-p)\times x[i]\)
對全部的點都求一遍,取最小值便可,複雜度\(\text O(NlogN)\)。
\(\\\)
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 100010 #define R register #define gc getchar #define inf 900000000000000000 using namespace std; typedef long long ll; inline ll rd(){ ll x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } ll n,ans=inf,x[N],y[N],sx[N],sy[N],sumx[N],sumy[N]; int main(){ n=rd(); for(R ll i=1,xx,yy;i<=n;++i){ xx=rd(); yy=rd(); sx[i]=x[i]=xx+yy; sy[i]=y[i]=xx-yy; } sort(sx+1,sx+1+n); sort(sy+1,sy+1+n); for(R ll i=1;i<=n;++i){ sumx[i]=sumx[i-1]+sx[i]; sumy[i]=sumy[i-1]+sy[i]; } for(R ll i=1,res;i<=n;++i){ ll px=lower_bound(sx+1,sx+1+n,x[i])-sx; ll py=lower_bound(sy+1,sy+1+n,y[i])-sy; res=px*x[i]-sumx[px]+sumx[n]-sumx[px]-(n-px)*x[i]; res+=py*y[i]-sumy[py]+sumy[n]-sumy[py]-(n-py)*y[i]; ans=min(ans,res>>1); } printf("%lld\n",ans); return 0; }