扩展问题:

  1. 从左边数起的第i只蚂蚁什么时候走出木杆?
  2. 所有蚂蚁从一开始到全部离开木杆共碰撞了多少次?
  3. 什么时候轮船可找到救生圈?

解答:

1. 从左边数起的第i只蚂蚁什么时候走出木杆?

现在来解决扩展1。这个解答甚是精妙,通俗点来说,我们假设每只蚂蚁都背着一袋粮食,任意两只蚂蚁碰头时交换各自的粮食然后调头。这种情况下,每次有一只蚂蚁离开木杆都意味着一袋粮食离开木杆(虽然可能已经不是它刚开始时背的那一袋了)。于是,我们可以求出每袋粮食离开木杆的时间(因为粮食是不会调头的)。又由于每袋粮食离开木杆的时间都对应某只蚂蚁离开木杆的时间,这是一种一一映射关系。现在我们要找到对应于第i只蚂蚁的那个映射。在此之前需要证明一个命题:

若一开始时有M只蚂蚁向左走,N−M只蚂蚁向右走,则最终会有M只蚂蚁从木杆左边落下,N−M只蚂蚁从木杆右边落下。

这个命题很容易证明:每次碰撞均不改变向左和向右的蚂蚁数量。于是,由于每次碰撞蚂蚁都会调头而不是穿过,最后必定是从左边数起的前M只蚂蚁从左边落下,后N−M只蚂蚁从木杆右边落下。由于我们知道每袋粮食是从哪边落下的,故左边落下的M袋粮食的离开木杆的时间就对应于从左边数起的前M只蚂蚁离开木杆的时间,右边的类似。因此,我们只需判断i和M的关系,便知道第i只蚂蚁是从左边还是右边落下。不妨假设是从左边落下,因此该蚂蚁落下的时间就等于从左边落下的第i袋粮食的落下时间。时间复杂度O(N),一遍扫描搞定。

2. 所有蚂蚁从一开始到全部离开木杆共碰撞了多少次?

对于扩展2,我们只需求得每个蚂蚁的碰撞次数,然后累加即可。在这里我们换一种思路,把碰撞调头看成不调头而继续向前(穿过),则容易看出原问题(碰撞次数)就变为求穿过的次数(因为速度大小不变,原来的每次碰撞都对应于现在的一次穿过)。则对于每只向左的蚂蚁,它只会“穿过”那些在它左边的向右走的蚂蚁。因此,每只蚂蚁“穿过”的蚂蚁次数等于刚开始时在它前进方向上与它前进方向相反的蚂蚁个数。时间复杂度也是O(N)。改为用粮食的观点来理解也是可以的。

3. 什么时候轮船可找到救生圈?

发现是轮船和救生圈的距离:(a-b)+b=a;
则找到的时间为a/(a+b-b)=1小时