#士兵战队问题

Description

在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可 以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士 兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),...,(x+n-1,y)。如何选择x 和y的值才能使士兵 们以最少的总移动步数排成一行。

计算使所有士兵排成一行需要的最少移动步数。

Format

Input

第1 行是士兵数n,1≤n≤10000。接下来n 行是士兵的初始位置,每行2 个整数x 和y,-10000≤x, y≤10000。

Output

第1行中的数是士兵排成一行需要的最少移动步数。

Samples

输入数据

5
1 2
2 2
1 3
3 -2
3 3

输出数据

8

问题分析

士兵排对分为x方向和y方向 所以我们可以把x和y分开来思考 类似与输油管道问题

对于Y方向

设n个士兵的Y轴坐标分别为:Y1,Y2 …… …… Yn, 他们最后站在同一行上,设目标坐标为Y0,
则n个士兵最终在Y轴的需要移动的总的步数值为S1:
S1=|Y1-Y0|+|Y2-Y0|+ …… …… +|Yn-Y0|
结论:Y0取所有Yi的中间值时可以使得S1达到最小(这个结论可以证明)

对于X方向

(1)首先需要对所有士兵的X轴坐标值进行排序(为了方便就近移动)
(2)然后,按从左至右的顺序依次求出每个士兵所对应的“最终位置”(最优),所移动的步数总和就是X轴方向上需要移动的步数
设排序后n个士兵在X轴坐标为: X1’,X2’ …… …… Xn’
他们最终位置”的X轴坐标值为:X0,X0+1,X0+2 …… …… X0+(n-1)
则n个士兵最终X轴的需要移动的总的步数值为S2:
S2=|X1’-X0| + |X2’-(X0+1)|+… +|Xn’-(X0+n-1)|
经过变换
S2=|X1’-X0|+ |(X2’-1)-X0|+ …+|(Xn’-(n-1))-X0|
注意到公式的形式与Y轴方向上的考虑一样,同样是n个已知数分别减去一个待定数后取绝对值,然后求和
结论:求出x1’, x2’-1,… Xn’-(n-1) 的中位数,即求得X0值,最后算出最优解。

样例代码

#include<bits/stdc++.h>

using namespace std;

int main(){

    int i,n,x;

    scanf("%d",&n);

    pair<int,int> P[n];

    int a[n],b[n];

    for(i=0;i<n;i++){

        cin>>P[i].first>>P[i].second;

         a[i]=P[i].first;

         b[i]=P[i].second;

    }

    sort(b,b+n);

    int sum=0;

    x = b[n/2];

    for(i=0;i<n;i++){

        sum+=abs(b[i]-x);

    }

     sort(a,a+n);

    for(i=0;i<n;i++){

        a[i] = a[i]-i;

    }

    sort(a,a+n);

    x = a[n/2];

    for(i=0;i<n;i++){

        sum+=abs(a[i]-x);

    }

    printf("%d",sum);

}

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值