题意:
有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
题解:
①切比雪夫距离和曼哈顿距离之间的转化
②对于这题,我们可以得到dis(i,j)=max(|xi-xj|,|yi-yj|),
③设x'=(x+y)/2,y'=(x-y)/2,那么dis(i,j)=|xi'-xj'|+|yi'-yj'|
④x,y轴可以分开统计
⑤先是统计x轴,将所有松鼠的x'排序
用前缀和求出某个松鼠到其他松鼠的X轴距离之和:
(X[i]*(i-1)-sum[1~i-1]) + (sum[i+1~n]-(n-i)*X[i])
⑥y轴同理
#include <cstdio> #include <algorithm> using namespace std; const int maxn=1e5+10; struct Node{ int num; double x,y; }a[maxn]; int n; double sumX[maxn]; double sumY[maxn]; double ans=1e20; bool cmpx(Node,Node); bool cmpy(Node,Node); void Prework(); void Query(int); int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ double x,y; scanf("%lf%lf",&x,&y); a[i].x=(x+y)/2,a[i].y=(x-y)/2; } Prework(); for(int i=1;i<=n;i++)Query(i); printf("%.0f ",ans); return 0; } bool cmpx(Node A,Node B){ return A.x<B.x; } bool cmpy(Node A,Node B){ return A.y<B.y; } void Prework(){ sort(a+1,a+1+n,cmpy); for(int i=1;i<=n;i++) sumY[i]=sumY[i-1]+a[i].y,a[i].num=i; sort(a+1,a+1+n,cmpx); for(int i=1;i<=n;i++) sumX[i]=sumX[i-1]+a[i].x; } void Query(int i){ double tmp=0; tmp+=(sumX[i]-sumX[i-1])*(i-1)-sumX[i-1]; tmp+=sumX[n]-sumX[i]-(n-i)*(sumX[i]-sumX[i-1]); int j=a[i].num; tmp+=(sumY[j]-sumY[j-1])*(j-1)-sumY[j-1]; tmp+=sumY[n]-sumY[j]-(n-j)*(sumY[j]-sumY[j-1]); ans=min(ans,tmp); }