编程之美 4.7蚂蚁爬杆
问题:有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。木杆很细,不能同时通过两只蚂蚁。开始时,蚂蚁头朝向任意(左或右),它们只会朝前或掉头,不会后退。当任意两只蚂蚁碰头是,两只蚂蚁会同时调头朝反向走。假设蚂蚁每秒走1厘米,编写程序,求所有蚂蚁都离开木杆的最短时间和最长时间。
解法一:
蛮力解法(brute force),枚举各蚂蚁的初始朝向,模拟每个蚂蚁的运动规律来解决。
解法二:
细心分析一下蚂蚁的运动及其行走的路径,可以得出一些有用的信息,例如两只蚂蚁A、B运动如下图所示:
A与B相遇,然后反向前进,最后A与B都离开了木杆,A总共走了6,B总共走了4。
若A与B相遇时,不是反向前进而是擦肩而过,继续前进,A走了5,B也走了5。
可以看出将“掉头走”看作“擦肩而过”,这样蚂蚁的运动就是独立的,其实A代替了B走,B代替了A走。
这样所有的蚂蚁运动轨迹可能与原来不同,但不影响所有蚂蚁离开木杆的最短时间和最长时间。
实现:
#include <iostream> using namespace std; void CalcTime(double PoleLen,double *xPos,int AntNum,double speed,double &tMin,double &tMax) { tMax=tMin=0; for(int i=0;i<AntNum;++i) { double curMax=0; double curMin=0; if (xPos[i]>(PoleLen/2)) { curMax=xPos[i]; } else { curMax=(PoleLen-xPos[i]); } curMin = PoleLen - curMax; if (tMax < curMax) { tMax = curMax; } if (tMin < curMin) //注意这里是小于因为是所有蚂蚁最短时间,取最短中最大的 { tMin = curMin; } } tMax/=speed; tMin/=speed; } void main() { double poleLength=27; double ants[5]={3,7,11,17,23}; double speed=1; double timeMax,timeMin; CalcTime(poleLength,ants,5,speed,timeMin,timeMax); cout<<"MaxTime:"<<timeMax<<endl; cout<<"MinTime"<<timeMin<<endl; }
MaxTime:24 MinTime11 请按任意键继续. . .
扩展问题:
1.第i只蚂蚁,什么时候走出木杆?
2.所有蚂蚁从一开始到全部离开木杆共碰撞了多少次?
参考资料: