算法分析士兵战队问题java代码_LFYZ-OJ ID: 1017 士兵站队问题

分析

该题和“输油管道问题”类似,只不过由一维问题编程了二维问题。可以将总步数分解为移动到水平线y位置的总步数ysteps和移动到序列x, x+1, x+2, ... , x+n-1位置的总步数xsteps。

ysteps的最小值容易计算,将所有士兵的纵坐标ypos[]排序后找出中位数,然后计算abs(xpos[1...n]-zws)即可。

xsteps的作如下分析:

共n个士兵,他们相应的X轴坐标为:x0, x1, x2 ... xn-1

设,士兵需要移动到的最终位置的x轴坐标值为:x, x+1, x+2, ..., x+(n-1)

则所求最优步数S=|x0-x|+|x1-(x+1)|+|x2-(x+2)|+...+|xn-1-(x+(n-1))|

经过变形S=|x0-x|+|(x1-1)-x|+|(x2-2)-x|+ ... +|(xn-1-(n-1))-x|

发现没有,问题已经变了,我们现在是在求序列x0, x1-1, x1-2, x1-3, ... xn-1-(n-1)与x绝对值之差的累加和的最小值。这和y方向上的计算是一样的了!因此还是采用取中位数的办法求得x值,最后算出最优解。

整理一下, 思路如下:

排序y序列ypos

求出y坐标序列ypos的中位数y_zws

计算y方向上的最小步数ysteps

排序x序列xpos

计算新序列xpos[i]-=(i-1),如xpos[5]-=4

排序x序列xpos

计算x方向上的最小步数xsteps

输出xsteps+ysteps

代码示例

#include

#include

using namespace std;

int xpos[10001];//士兵x坐标集合

int ypos[10001];//士兵y坐标集合

void qsort(int Data[], int low, int high){ //快速排序

int i=low, j=high, m=Data[(low+high)/2];

while(i<=j){

while(Data[i]

while(Data[j]>m) j--;

if(i<=j){

int t=Data[i];

Data[i]=Data[j];

Data[j]=t;

i++, j--;

}

}

if(j>low) qsort(Data, low, j); //对右部分排序

if(i

}

int main(){

int n, steps=0;

scanf("%d", &n);

for(int i=1; i<=n; i++)scanf("%d%d", &xpos[i], &ypos[i]);

qsort(ypos, 1, n); //排序ypos序列

qsort(xpos, 1, n); //排序xpos序列

for(int i=1; i<=n; i++)xpos[i]-=(i-1); //生成新的xpos序列

qsort(xpos, 1, n); //重排xpos序列

for(int i=1; i<=n; i++) //计算步数

steps+=(abs(xpos[i]-xpos[n/2+1])+abs(ypos[i]-ypos[n/2+1]));

printf("%d", steps);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值