士兵排队

题目:

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


题目分析:

显然,这个二维问题是可以转换为两个独立的一维问题的。首先确定Y很简单。

,从数学上证明,中位数是最优解释y的值。

其次确定x的最优值情况,不失一般性不妨假设x[0]<=x[1]<=x[2]<=...<=x[n-1];

即求|x-x[0]|+|x+1-x[1]|+|x+2-x[2]|+...+|x+i-x[i]+|x+n-1-x[n-1]|的最小值,由于常数对x的取值没有影响,

可转化为求|x-x[0]|+|x-x[1]|+|x-x[2]|+...+|x-x[n-1]|最优


源代码实现:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int a[101],b[101],c[101],n,t;//t组测试数据,n<100,
                                //a数组存储x,b数组存储y
    cin>>t;
    while(t--){
        int x,y;
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>x>>y;
            a[i]=x;
            b[i]=y;
        }
        sort(b,b+n);
        //确定最优值y
        y=b[n/2];
        sort(a,a+n);
        for(int i=0;i<n;i++){//去掉|x-x[0]|+|x+1-x[1]|+|x+2-x[2]|+...
                             //+|x+i-x[i]+|x+n-1-x[n-1]|中的i值
           a[i]=a[i]-i;
        }
        sort(a,a+n);
        //确定最优值x
        x=a[n/2];

        int minstep=0;//最小步数
        sort(a,a+n);//重新排序,(不是是否有用,先保留)
        for(int i=0;i<n;i++){
            minstep+=(a[i]-x)+(b[i]-y);
        }
        cout<<minstep<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值