【POJ1723】SOLDIERS(中位数,货仓选址)

problem

  • 平面上有N(N<=10000)个点
  • 求这些点变成一条水平线的最小移动步数

solution

  • 对于y轴,易证得在中位数处取到最优,直接排序统计即可。
  • 对于x轴,因为要保证相对顺序,(比如:原来三个士兵的x坐标是 -1 5 6,那么在他们移动之后,假设移动成一条直线之后,起点是原来-1的那个士兵,现在的坐标是9,那么他们之间的相对位置就是9 10 11…)
    1、假设最后水平线的起点是a,根据上面的理论可以得到 x’[0] = a, x’[1] = a+1, x’[2] = a+2…
    2、移项,可以得到x[0] - 0 = a, x[1] - 1 = a, x[2] - 2 = a…..
    3、所以我们把每个x[i] 都减去i,然后再从小到大排序,这样就保证在相对位置不变的情况下成一条水平线。然后把距离差求和就可以了。

codes

#include
#include
#include
using namespace std;
int a[10010], b[10010];
int main(){
    int n;  cin>>n;
    for(int i = 1; i <= n; i++)
        cin>>a[i]>>b[i];
    sort(b+1,b+n+1);
    int y = b[n+1>>1];
    sort(a+1,a+n+1);
    for(int i = 1; i <= n; i++)a[i]-=i;
    sort(a+1,a+n+1);
    int x = a[n+1>>1];
    int ans = 0;
    for(int i = 1; i <= n; i++)
        ans += abs(a[i]-x)+abs(b[i]-y);
    cout<'\n';
    return 0;
}

你可能感兴趣的:(算法)