问题链接:POJ1723 SOLDIERS。
问题简述:有N个士兵,每个士兵开始站的坐标是(x,y),现在使得将N个士兵站在同一个水平线(即所有士兵的y坐标相同)并且x坐标相邻,每个士兵每次可以移动一个位置(分别在x和y方向移动)。求出最少的移动步数。
问题分析:
这是一个最优化问题,可以使用中位数计算来解决。
x方向和y方向可以分别来考虑。
y方向就是一个简单的中位数计算。
x方向是坐标相邻,可以先将x位置排序,然后往中间靠,也是一个中位数计算问题。x方向分别移动到a+i的位置,那么士兵就相邻了,即x[i]=a+i,那么x[i]-i=a。用中位数来算的话,首先将x方向进行排序,然后让x[i]=x[i]-i,再次排序后求中位数即可。
程序说明:(略)
AC的C++语言程序如下:
/* POJ1723 SOLDIERS */
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10000;
int x[N], y[N];
int main()
{
int n;
while(cin >> n) {
for(int i=0; i<n; i++)
cin >> x[i] >> y[i];
sort(x, x + n);
for(int i=0; i<n; i++)
x[i] -= i;
sort(x, x + n);
sort(y, y + n);
int ans = 0, x_median, y_median;
if(n % 2 == 1) {
x_median = x[n / 2];
y_median = y[n / 2];
} else {
x_median = (x[n / 2 - 1] + x[n / 2]) / 2;
y_median = (y[n / 2 - 1] + y[n / 2]) / 2;
}
for(int i=0; i<n; i++)
ans += abs(x_median - x[i]) + abs(y_median - y[i]);
cout << ans << endl;
}
return 0;
}