Description
有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
Input
第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5 下面N行,每行给出x,y表示其家的坐标。 -10^9<=x,y<=10^9
Output
表示为了聚会走的路程和最小为多少。
首先等价变换,旋转坐标系45度,将点(x,y)改为((x+y)/2,(x-y)/2),原距离定义改为曼哈顿距离
枚举每个点,分别计算其余点与其x,y坐标差之和
#include<cstdio> #include<algorithm> char buf[10000005],*ptr=buf-1; inline int input(){ int x=0,c=*++ptr,f=1; while(c>57||c<48){if(c=='-')f=-1;c=*++ptr;} while(c>47&&c<58)x=x*10+c-48,c=*++ptr; return x*f; } const int N=100500; int n; int x0[N],y0[N],xv[N],yv[N]; long long xs[N],ys[N],ans=1ll<<62; int main(){ fread(buf,1,10000000,stdin); n=input(); for(int i=1;i<=n;i++){ int x=input(),y=input(); x0[i]=xv[i]=x+y; y0[i]=yv[i]=x-y; } std::sort(xv+1,xv+n+1); std::sort(yv+1,yv+n+1); for(int i=1;i<=n;i++){ xs[i]=xs[i-1]+xv[i]; ys[i]=ys[i-1]+yv[i]; } for(int i=1;i<=n;i++){ int m=std::lower_bound(xv+1,xv+n+1,x0[i])-xv; long long s=(1ll*x0[i]*m-xs[m])+(xs[n]-xs[m]-1ll*x0[i]*(n-m)); m=std::lower_bound(yv+1,yv+n+1,y0[i])-yv; s+=(1ll*y0[i]*m-ys[m])+(ys[n]-ys[m]-1ll*y0[i]*(n-m)); if(s<ans)ans=s; } printf("%lld ",ans>>1); return 0; }