题目如下:
SOLDIERS
Description
N soldiers of the land Gridland are randomly scattered around the country. A position in Gridland is given by a pair (x, y) of integer coordinates. Soldiers can move - in one move, one soldier can go one unit up, down, left or right (hence, he
can change either his x or his y coordinate by 1 or -1).
The soldiers want to get into a horizontal line next to each other (so that their final positions are
(x, y), (x+1,y), ..., (x+N-1, y), for some x and y). Integers x and y, as well as the final
order of soldiers along the horizontal line is arbitrary.
The goal is to minimise the total number of moves of all the soldiers that takes them into such configuration.
Two or more soldiers must never occupy the same position at the same time.
Input
The first line of the input contains the integer N, 1 <= N <= 10000, the number of soldiers.
The following N lines of the input contain initial positions of the soldiers : for each i, 1 <= i <= N, the (i+1)st line of the input file contains a pair of integers x[i] and y[i] separated by a single blank character, representing the coordinates
of the ith soldier, -10000 <= x[i],y[i] <= 10000.
Output
The first and the only line of the output should contain the minimum total number of moves that takes the soldiers into a horizontal line next to each other.
Sample Input Sample Output
5 8
1 2
2 2
1 3
3 -2
3 3
题目分析:
通过适当的移动顺序和移动路线可以使得同一时刻不会有两名士兵站在同一点。
题目要求移动的最少步数
题目要求可转化为求士兵站立的“最终位置”,即如何取“最终位置”使得士兵移动的步数最少
1. Y轴方向上的考虑
设目标坐标为Y0,即n个士兵最终需要移动到的Y轴的坐标值为M
n个士兵的Y轴坐标分别为:
Y1,Y2 …… …… Yn
移动步数
S=|Y1-Y0|+|Y2-Y0|+ …… …… +|Yn-Y0|
结论:Y0取所有Yi的中间值时可以使得S达到最小。
(可以证明)
解决办法:
1.对所有的Y轴坐标进行排序(O(nlogn))或者进行线性时间选择(O(n))然后取“中间”点的Y轴坐标值作为最佳位置Y0的值
2.通过公式求出Y轴方向上移动的最优步数
2. X轴方向上的考虑
(1)首先需要对所有士兵的X轴坐标值进行排序
(2)然后,按从左至右的顺序依次移动到每个士兵所对应的“最终位置”(最优),所移动的步数总和就是X轴方向上需要移动的步数
设排序后n个士兵在X轴坐标为:
X1’,X2’ …… …… Xn’
他们最终位置”的X轴坐标值为:
k,k+1,k+2 …… …… k+(n-1)
则所求移动的步数
S=|X1’-k| + |X2’-(k+1)|+
…… +|Xn’-(k+(n-1)|
经过变形
S=|X1’-k|+ |(X2’-1)-k|+
…… +|(Xn’-(n-1))-k|
注意到公式的形式与Y轴方向上的考虑一样,同样是n个已知数分别减去一个待定数后取绝对值,然后求和
问题转化为:
求出x1’, x2’-1,… Xn’-(n-1)的中位数,即求得k值,最后算出最优解。
代码实现如下:
#include<stdio.h>
#include<math.h>
int partition(int *a,int low,int high){
int key = a[low] ,i = low,t = high;
while(low < high){
while(low < high && a[high]>= key) high--;
a[low] = a[high];
while(low < high && a[low] <= key) low++;
a[high] = a[low];
}
a[low] = key;
return low;
}
void qSort(int *a,int low ,int high){
int k;
if(low < high){
k = partition(a,low,high);
qSort(a,low,k-1);
qSort(a,k+1,high);
}
}
int RandSelect(int *a,int low ,int high,int k){
int i = partition(a,low,high);
int j = i-low+1;
if(j == k){
return a[i];
}else if(j > k){
return RandSelect(a,low,i-1,k);
}else{
return RandSelect(a,i+1,high,k-j);
}
}
int main(){
int xKey,yKey,x[10010],y[10010],x1[10010],n,sum = 0;
scanf("%d",&n);
int i = 0;
for(i = 0;i < n;i++){
scanf("%d%d",&x[i],&y[i]);
}
qSort(y,0,n-1);
qSort(x,0,n-1);
for(i = 0;i < n;i ++){
x1[i] = x[i]-i;
}
qSort(x1,0,n-1);
xKey = x1[n/2];
yKey = y[n/2];
for(i = 0;i < n;i ++){
sum += abs(x1[i] - xKey);
sum += abs(y[i] - yKey);
}
printf("%d",sum);
return 0;
}