3170: [Tjoi2013]松鼠聚会
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1670 Solved: 885
[Submit][Status][Discuss]
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
表示为了聚会走的路程和最小为多少。
Sample Input
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
Sample Output
20
HINT
Source
题意:N个点,求某一个点到其他点的切比雪夫距离之和最小化;
题解:
推荐一篇页面比较好讲得很清楚的博客:https://www.cnblogs.com/zwfymqz/p/8253530.html
两个点(x1,y1) 和 (x2,y2)
切比雪夫距离:max(|x1-x2|,|y1-y2|)
曼哈顿距离:|x1-x2|+|y1-y2|
先介绍绝对值的两个性质:|a|+|b| = max(|a+b|,|a-b|) max(|a|,|b|) = |(a+b)/2|+|(a-b)/2|
可以利用数轴理解一下;
利用上面的性质可以知道:
若:(x,y) – > (x-y,x+y) 则新图的切比雪夫距离为原图的曼哈顿距离;
若:(x,y) – > (x-y,x+y) 则新图的切比雪夫距离为原图的曼哈顿距离;
若:(x,y) – > ((x-y)/2,(x+y)/2) 则新图的曼哈顿距离为原图的切比雪夫距离;
为什么要转化呢?
切比雪夫不好处理,转化后对曼哈顿距离分x,y排序,预处理某个值到前面的曼哈顿距离之和,可以做到O(1)查询,此题直接枚举哪个点;
另外如果最近的点不要求在这些点里面而是平面的任何一个点,分别贪心选取x坐标,y坐标的排序后的中位数,注意切比雪夫转曼哈顿,有可能不是整点,要求整点还需要特判一下;
1 2 #include<cstdio> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 #include<cmath> 8 #include<vector> 9 #include<stack> 10 #include<map> 11 #define Run(i,l,r) for(int i=l;i<=r;i++) 12 #define Don(i,l,r) for(int i=l;i>=r;i--) 13 #define ll long long 14 #define inf 0x3f3f3f3f 15 using namespace std; 16 const int N=100010; 17 int n,px[N],py[N]; 18 ll upx[N],dnx[N],upy[N],dny[N]; 19 struct data{ 20 int x,id; 21 bool operator <(const data&A)const{ 22 return x<A.x; 23 } 24 }X[N],Y[N]; 25 int main(){ 26 // freopen("bzoj3170.in","r",stdin); 27 // freopen("bzoj3170.out","w",stdout); 28 scanf("%d",&n); 29 for(int i=1;i<=n;i++){ 30 int a,b; 31 scanf("%d%d",&a,&b); 32 X[i]=(data){a-b,i}; 33 Y[i]=(data){a+b,i}; 34 } 35 sort(X+1,X+n+1); 36 sort(Y+1,Y+n+1); 37 for(int i=1;i<=n;i++){ 38 px[X[i].id]=i; 39 py[Y[i].id]=i; 40 } 41 ll ans=1e18; 42 for(int i=1;i<=n;i++){ 43 upx[i]=upx[i-1]+1ll*(i-1)*(X[i].x-X[i-1].x); 44 upy[i]=upy[i-1]+1ll*(i-1)*(Y[i].x-Y[i-1].x); 45 } 46 for(int i=n;i;i--){ 47 dnx[i]=dnx[i+1]+1ll*(n-i)*(X[i+1].x-X[i].x); 48 dny[i]=dny[i+1]+1ll*(n-i)*(Y[i+1].x-Y[i].x); 49 } 50 for(int i=1;i<=n;i++){ 51 ans=min(ans,upx[px[i]]+dnx[px[i]]+upy[py[i]]+dny[py[i]]); 52 } 53 printf("%lld ",ans>>1); 54 return 0; 55 }//by tkys_Austin;