题意:一些士兵站在矩阵的一些方格内,现要把他们移动到一横排,并连续地排成一队,问最少需要移动多少步。
分析:
货仓选址问题,相关证明可以浏览:https://www.cnblogs.com/LLTYYC/p/9537677.html
货仓选址核心思想简短描述:对于一个数列,其各点到此数列的中位数处的距离之和是最短的。
对于纵坐标,假设选取的基准点为,那么移到同一排的步数之和为
,所以直接求出各点到中位数处的距离即可。对于横坐标,我们假设所选取的最终基准点为
,那么,所要求的距离即为
。令
=
,即相当于横坐标为
的货仓选址问题,因此只要找出
的中位数即可。因此,分别对横纵坐标两个数列进行排序。再将横纵坐标到中位数的距离加和,即为所求
#include<iostream>
#include<algorithm>
using namespace std;
#define size 10010 //N <= 10000
int main() {
int ans = 0;
int N;
int x[size];
int y[size];
cin >> N;
for (int i = 0; i < N; i++) {
cin >> x[i];
cin >> y[i];
}
sort(x, x + N); //对横坐标进行排序
sort(y, y + N); //对纵坐标进行排序
int middle = N / 2; //中位数的位置(如果总数是偶数,选择其中的任意一个,答案相同)
for (int i = 0; i < N; i++)
x[i] -= i; //构造新数列 Z[i] = X[i]-i
sort(x, x + N); //对新数列排序
for (int i = 0; i < N; i++)
ans += (abs(x[i] - x[middle]) + abs(y[i] - y[middle])); //对横向和纵向移动距离进行求和
cout << ans << endl;
return 0;
}