poj 1723 Soldiers【中位数】By cellur925
题目大意:平面上有n个士兵,给出每个士兵的坐标,求出使这些士兵站好所需要的最少移动步数。站好要求:所有士兵y相等,x相邻。即达到 (x,y), (x+1, y), (x+2,y)……的状态。(每行不相邻)
$Sol$
我们很容易能想到,让所有士兵y相等就要把他们都移动到所有士兵y的中位数上。这时可能存在有士兵重合在同一格点的情况。后来x轴的情况:
x轴时,先进行一次排序后,假设水平线上的n个点存储在数组a[n]中,则第一个点a[0]最终排序后的位置是addr,a[1]的最终位置是(addr+1),a[2]的最终位置是(addr+2)……a[n]------->(addr+n)。分析则有:addr = a[0]-0 = a[1]-1 = a[2]-2 = ... = a[i]-i = ... = a[n]-n。故可将(a[i]-i)视为一个新的point,并将n各新的point移动到同一个位置addr。可以看出,将x轴的问题转化为了和y轴相同的问题。最后得出最少步数。 --------------------- 本文来自 crev 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/wutong_v/article/details/51603946?utm_source=copy
也就是说,各个士兵在行上的相对位置是没有变的。
$Code$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 int n,sta,ans; 7 struct node{ 8 int x,y; 9 }p[20000]; 10 11 bool cmp(node a,node b) 12 { 13 return a.y<b.y; 14 } 15 16 bool cmp2(node a,node b) 17 { 18 return a.x<b.x; 19 } 20 21 int main() 22 { 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++) 25 scanf("%d%d",&p[i].x,&p[i].y); 26 sort(p+1,p+1+n,cmp); 27 sta=p[(n+1)>>1].y; 28 for(int i=1;i<=n;i++) 29 ans+=abs(sta-p[i].y); 30 31 sort(p+1,p+1+n,cmp2); 32 for(int i=1;i<=n;i++) p[i].x-=i; 33 sort(p+1,p+1+n,cmp2); 34 sta=p[(n+1)>>1].x; 35 for(int i=1;i<=n;i++) 36 ans+=abs(sta-p[i].x); 37 printf("%d",ans); 38 return 0; 39 }
独立意志与自由思想是必须争的,且须以生死力争。