曼哈頓距離&切比雪夫距離
阿新 • • 發佈:2018-12-14
什麼是切比雪夫距離?什麼是曼哈頓距離?
傻傻分不清,沒關係,看:
曼哈頓距離
設平面空間記憶體在兩點,它們的座標為(x1,y1),(x2,y2)
則dis=|x1−x2|+|y1−y2|
即兩點橫縱座標差之和
切比雪夫距離
設平面空間記憶體在兩點,它們的座標為(x1,y1),(x2,y2)
則dis=max(|x1−x2|,|y1−y2|)
即兩點橫縱座標差的最大值
比如這個圖,A,B兩點的曼哈頓距離就是
切比雪夫距離就是
既然都提到這兩個距離了,就免不了要講講它們的相互轉化
將一個點(x,y)的座標變為(x+y,x−y)後,原座標系中的曼哈頓距離 = 新座標系中的切比雪夫距離
將一個點(x,y)的座標變為後,原座標系中的切比雪夫距離 = 新座標系中的曼哈頓距離
這個證明也很容易,有興趣的同學可以來皮一下
我就不在這裡贅述了
然而有什麼用呢??這麼多奇奇怪怪的定義,真是讓人摸不著頭腦
但事實上,可有用了呢
切比雪夫距離由於要求max 很多時候不是很好優化,對於一個點,計算其他點到該的距離的複雜度為O(n)(因為要列舉)
而曼哈頓距離只有求和以及取絕對值兩種運算,我們把座標排序後可以去掉絕對值的影響,進而用字首和優化,可以把複雜度降為O(1),也可以支援很多次的運算
而有一個細節需要注意一下:
在切比雪夫距離轉曼哈頓距離的時候,座標本是要除以2的,但考慮到精度的問題,我們一般都會將除以2 這一步操作放到最後 這樣也是正確的,形象的理解可以說成,曼哈頓座標系是通過切比雪夫座標系旋轉45度後,再縮小到原來的一半得到的。
#include<bits/stdc++.h> #define ll long long #define N 100009 #define in read() using namespace std; inline int read(){ char ch;int f=1,res=0; while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1; while(ch>='0'&&ch<='9'){ res=(res<<3)+(res<<1)+ch-'0'; ch=getchar(); } return f==1?res:-res; } ll ans=1ll<<50ll,sumx[N],sumy[N];//一開始ans又初始小了~~~~~悲傷 int n,x[N],y[N],xx[N],yy[N]; ll solve(int now){//現在要到 n 的家裡去 ll res=0; int pos=lower_bound(xx+1,xx+n+1,x[now])-xx; res+=1ll*pos*x[now]-sumx[pos]+sumx[n]-sumx[pos]-1ll*(n-pos)*x[now]; pos=lower_bound(yy+1,yy+n+1,y[now])-yy; res+=1ll*pos*y[now]-sumy[pos]+sumy[n]-sumy[pos]-1ll*(n-pos)*y[now]; return res; } int main(){ n=in; int i,j,k; for(i=1;i<=n;++i) { int a=in;int b=in; x[i]=xx[i]=a+b; y[i]=yy[i]=a-b; } sort(xx+1,xx+n+1); sort(yy+1,yy+n+1); for(i=1;i<=n;++i){ sumx[i]=sumx[i-1]+xx[i]; sumy[i]=sumy[i-1]+yy[i]; } for(i=1;i<=n;++i) ans=min(ans,solve(i)); cout<<ans/2; return 0; }