NYOJ 1274排兵布阵

来源:互联网 发布:餐饮取名软件 编辑:程序博客网 时间:2024/09/21 09:26

排兵布阵

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述
    在一个划分成网格的操场上,n个士兵散乱的站在网格上,网格点由整数坐标(x,y)表示,士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照将军的命令,士兵们要整齐的排列成一个水平队列,即排列成(x, y),(x+1, y),……,(x+n-1, y)。如何选择x和y的值才能使士兵们以最少的总移动步数排成一行。请计算使所有士兵排成一行需要的最少移动步数。
输入
多组测试数据。
每组数据的第一行是士兵数n,1≤n≤10000。接下来n行是士兵的位置,每行2个整数x和y,-10000≤x,y≤10000.
输出
输出使所有士兵排成一行需要的最少移动步数。
样例输入
51 22 21 33 -23 3
样例输出
8
分析:在解答这个问题之前,我们先思考这样一个问题:有n个整数a[1], a[2], ……, a[n],对这n个数进行变形,使得a[1]=a[2]=……=a[n]=k。令sum=Sigma{ abs(a[i] - k}(i=1,2,……,n)。求sum的最小值。

关于k的选择,可以证明当k选择这n个数的中位数时,sum最小(证明略)。解决了上面的问题,则这个问题就比较容易解决了。

在这个问题中,因为最后要把所有的士兵排列成(x, y),(x+1, y),……,(x+n-1, y的形式,而y的值是相同的,并且X轴方向和Y轴方向的移动相互不影响,所以对于Y轴方向的处理,就和上面的问题相同了。

受到处理Y轴方向的启发,对于X轴方向上的处理,可以采取类似的方法,不同的就是每个士兵x的值并不相同,而是后一个比前一个大1。那么对于X轴上的处理,只需找出一个中间值mid,横坐标xmid大的士兵都排列在mid右边,横坐标xmid小的士兵都排列在mid左边,这样求出的结果就是X轴方向移动的最小值。最后将X轴方向和Y轴方向移动的最小值相加,结果就是最终的最小值。而mid就是所有士兵横坐标x的中位数。

 参考代码:

#include <cstdio>#include <algorithm>using namespace std;const int MaxN = 1e4 + 10;struct Soldier {    int x, y;} a[MaxN];// Y轴排序bool comp_y(Soldier A, Soldier B) {    if(A.y != B.y) return A.y < B.y;    return A.x < B.x;}// X轴排序bool comp_x(Soldier A, Soldier B) {    if(A.x != B.x) return A.x < B.x;    return A.y < B.y;}int main() {    int n;    while(~scanf("%d", &n)) {        for(int i = 0; i < n; ++i)            scanf("%d%d", &a[i].x, &a[i].y);        sort(a, a + n, comp_y);        int flag_y = a[n / 2].y; // 取得y的中位数        sort(a, a + n, comp_x);        int flag_x = a[n / 2].x; // 取得x的中位数        int flag_id;        for(int i = 0; i < n; ++i) {            if(a[i].x == flag_x) {                flag_id = i;                break;            }        }        int ans = 0;        for(int i = flag_id, cur_x = flag_x; i < n; ++i, ++cur_x) // 右边            ans += (abs(a[i].x - cur_x) + abs(a[i].y - flag_y));        for(int i = flag_id - 1, cur_x = flag_x - 1; i >= 0; --i, --cur_x) // 左边            ans += (abs(a[i].x - cur_x) + abs(a[i].y - flag_y));        printf("%d\n", ans);    }    return 0;}


0 0