问题描述:http://poj.org/problem?id=1723
问题分析:
通过适当的移动顺序和移动路线可以使得同一时刻不会有两名士兵站在同一点。
题目要求移动的最少步数
题目要求可转化为求士兵站立的“最终位置”,即如何取“最终位置”使得士兵移动的步数最少
1. Y轴方向上的考虑(找出Y0的值)
设目标坐标为Y0,即n个士兵最终需要移动到的Y轴的坐标值为M
n个士兵的Y轴坐标分别为:
Y1,Y2 …… …… Yn
移动步数
S=|Y1-Y0|+|Y2-Y0|+ …… …… +|Yn-Y0|
结论:Y0取所有Yi的中间值时可以使得S达到最小。
(可以证明)
中位数是Y0;
解决办法:
1.对所有的Y轴坐标进行排序(O(nlogn))或者进行线性时间选择(O(n))然后取“中间”点的Y轴坐标值作为最佳位置Y0的值
2.通过公式求出Y轴方向上移动的最优步数
2. X轴方向上的考虑
(1)首先需要对所有士兵的X轴坐标值进行排序
(2)然后,按从左至右的顺序依次移动到每个士兵所对应的“最终位置”(最优),所移动的步数总和就是X轴方向上需要移动的步数
设排序后n个士兵在X轴坐标为:
X1’,X2’ …… …… Xn’
他们最终位置”的X轴坐标值为:
X0,X0+1,X0+2 …… …… X0+(n-1)
则所求移动的步数
S=|X1’-X0| + |X2’-(X0+1)|+ …… +|Xn’-(X0+(n-1)|
经过变形
S=|X1’-X0|+ |(X2’-1)-X0|+ …… +|(Xn’-(n-1))-X0|
注意到公式的形式与Y轴方向上的考虑一样,同样是n个已知数分别减去一个待定数后取绝对值,然后求和
问题转化为:
求出x1’,x2’-1,…Xn’-(n-1)的中位数,即求得X0值,最后算出最优解。
#include<stdio.h>
#include<math.h>
void Swap(int a[],int i,int j)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
void Quick_sort(int a[],int left,int right)
{
if(left>right)
return;
int pivot=a[right];
int p=left;
for(int i=left;i<right;i++)
if(a[i]<pivot)
Swap(a,i,p++);
Swap(a,right,p);
Quick_sort(a,left,p-1);
Quick_sort(a,p+1,right);
}
int qiujie(int a[],int n)
{
Quick_sort(a,0,n-1);
int sum=0,m=n/2;
for(int i=0;i<n;i++)
sum+=abs(a[i]-a[m]);
return sum;
}
int main()
{
int n;
scanf("%d",&n);
int x[n],y[n],z[n];
for(int i=0;i<n;i++)
scanf("%d%d",&x[i],&y[i]);
Quick_sort(x,0,n-1);
for(int i=0;i<n;i++)
z[i]=x[i]-i;
printf("%d",qiujie(y,n)+qiujie(z,n));
return 0;
}