蚂蚁爬杆问题php,蚂蚁爬杆问题

【问题】n只蚂蚁以每秒1cm的速度在长为Lcm上的杆子上爬行。当蚂蚁爬到杆子的两个端点的时候,就会从杆子上掉落下来。规定两只蚂蚁相遇的时候,不能交叉通过,只能各自掉头爬回去。假设对于蚂蚁 i 来说,它的初始位置与杆子左端的距离是Xi,但是不知道它的朝向。请计算所有蚂蚁掉落杆子需要的最短时间和最长时间。

限制条件是

1<><>

1<><>

0<>Xi<>

148595445_1_20181202030156638

以上是一道经典的POJ题目。假设输入为

L=10

n=3

X={2,6,7}

输出为

min=4(此时蚂蚁的朝向可以依次是左,右,右)

148595445_2_20181202030156747

max=8(此时蚂蚁的朝向可以依次是右,右,右)

148595445_3_20181202030156825

148595445_4_20181202030156966

这个题目的复杂性在于我们不知道蚂蚁的初始朝向。很容易想到的一个直观的方法是穷举法,即列举出蚂蚁所有初始朝向的组合,然后计算出每种蚂蚁组合掉落时间,找出其中最短的时间和最长的时间。

下面列出了所有朝向组合以及算出对应的蚂蚁掉落时间(见下图):

148595445_5_20181202030156997

148595445_6_20181202030157279

我们来看看这种算法的复杂性。由于每种蚂蚁开始的朝向都有2种可能,n只蚂蚁就有2*2*2*...*2=2**n(2的n次方)可能性。这是一个指数函数。在n比较小的时候,还是可行的,但是随着n的增长,复杂性会急剧增长,参考下面的表格。

148595445_7_20181202030157372

因此这种算法在n较大的情况下不可行,我们必须另想别法。

148595445_8_20181202030157497

首先,考虑最短时间。如果所有蚂蚁都向离它较近的那个端点方向爬行,那么蚂蚁就不会相遇,而且不可能在比它更短的时间内走完,这种情形肯定是最短时间。此时只要找出每只蚂蚁到端点较近的距离,然后从中找出一个最大值就可以。

再考虑最长的时间,是否就是所有蚂蚁向离它较远的那个端点方向爬行就可以了呢?还不能肯定,因为此时需要考虑蚂蚁相遇掉头的情况。

让我们看看两只蚂蚁相遇的情形:

148595445_9_20181202030157529

假设蚂蚁1(朝右)与蚂蚁2(朝左)在距离杆子左端的X处相遇,那么蚂蚁1将掉头向左爬回去,而蚂蚁2也将掉头向右爬回去。

148595445_10_20181202030157607

之后它们不再相遇,一直到两只蚂蚁全部掉下杆子为止。此时蚂蚁1在X秒后在杆子的左端掉下杆子,而蚂蚁2在杆子的右端掉下花费时间为(10-X)秒。因此它们全部掉落杆子的时间是X和10-X中较大的值:max(X,10-X)。

事实上,如果我们假设两只蚂蚁相遇后,它们保持原来方向继续向前爬行,两只蚂蚁全部掉落杆子的时间不会变化。

148595445_11_20181202030157732

上图中,两只蚂蚁相遇后,蚂蚁1保持向右爬行,到它掉落杆子的右端时间为(10-X)秒,而蚂蚁2保持向左爬去,到它掉落杆子左端的时间是X秒。于是它们全部掉落的时间还是X和10-X中较大的值:max(X,10-X)。

148595445_12_20181202030157841

两只蚂蚁的情形可以推广到n只蚂蚁的情形。这样,我们可以假设每只蚂蚁都是独立运动的,并且每只蚂蚁都向离它较远的杆子端点爬去,从中找出最长时间,它就是所有蚂蚁掉落杆子的最长时间。因此通过找出所有蚂蚁中离杆子端点最大距离可以计算出最长时间。

对所有蚂蚁检查一次它到两端的距离即可,也就是算法的复杂度是O(n)。可以满足输入限制条件n<>

148595445_13_20181202030157997

下面是对应的一段C/C++程序的类代码。

int  L, n ;        //L是杆子长度,n是蚂蚁数目

int x[LIMIT];//数组x记录每个蚂蚁离杆子左侧的距离,LIMIT是最大的蚂蚁数

int max(int a,int b) //max函数返回两数中的较大值

{

int result;

result = b;

if (a>b) result = a;

return result;

}

int min(int a,int b) //min函数返回两数中的较小值

{

int result;

result = b;

if (a

return result;

}

void calculateTime()

{

int minTime = 0; //minTime是最短时间

int maxTime = 0; //maxTime是最长时间

for (int i=0;i<>

{

minTime = max (minTime, min(x[i], L-x[i]));

maxTime = max (maxTime, max(x[i], L-x[i]));

}

printf('%d %d\n',minTime,maxTime);

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值