您的位置:首页 > 其它

bzoj3170 [Tjoi 2013]松鼠聚会

2016-05-21 21:04 239 查看

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
,y0
,xv
,yv
;
long long xs
,ys
,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
-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
-ys[m]-1ll*y0[i]*(n-m));
if(s<ans)ans=s;
}
printf("%lld\n",ans>>1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: