题目:
在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何选择x和y的值才能使士兵们以最少的总移动步数排成一列。
题目分析:
显然,这个二维问题是可以转换为两个独立的一维问题的。首先确定Y很简单。
,从数学上证明,中位数是最优解释y的值。
其次确定x的最优值情况,不失一般性不妨假设x[0]<=x[1]<=x[2]<=...<=x[n-1];
即求|x-x[0]|+|x+1-x[1]|+|x+2-x[2]|+...+|x+i-x[i]+|x+n-1-x[n-1]|的最小值,由于常数对x的取值没有影响,
可转化为求:|x-x[0]|+|x-x[1]|+|x-x[2]|+...+|x-x[n-1]|最优
源代码实现:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[101],b[101],c[101],n,t;//t组测试数据,n<100,
//a数组存储x,b数组存储y
cin>>t;
while(t--){
int x,y;
cin>>n;
for(int i=0;i<n;i++){
cin>>x>>y;
a[i]=x;
b[i]=y;
}
sort(b,b+n);
//确定最优值y
y=b[n/2];
sort(a,a+n);
for(int i=0;i<n;i++){//去掉|x-x[0]|+|x+1-x[1]|+|x+2-x[2]|+...
//+|x+i-x[i]+|x+n-1-x[n-1]|中的i值
a[i]=a[i]-i;
}
sort(a,a+n);
//确定最优值x
x=a[n/2];
int minstep=0;//最小步数
sort(a,a+n);//重新排序,(不是是否有用,先保留)
for(int i=0;i<n;i++){
minstep+=(a[i]-x)+(b[i]-y);
}
cout<<minstep<<endl;
}
return 0;
}