北大ACM1723——士兵排队问题

本文介绍了一个关于士兵在二维网格中移动并排列成一行的问题。通过分析Y轴和X轴的移动策略,找到使所有士兵移动距离最短的方法,并提供了一种有效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目如下:

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轴坐标进行排序(Onlogn))或者进行线性时间选择(On))然后取中间点的Y轴坐标值作为最佳位置Y0的值
    2.通过公式求出Y轴方向上移动的最优步数


2. X轴方向上的考虑
  1首先需要对所有士兵的X轴坐标值进行排序
  2然后,按从左至右的顺序依次移动到每个士兵所对应的最终位置(最优),所移动的步数总和就是X轴方向上需要移动的步数
  设排序后n个士兵X轴坐标为:

X1’X2’ …… …… Xn’

他们最终位置X轴坐标值为:

kk+1k+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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值