蚂蚁爬杆问题
题目:
有一根27厘米长的细木杆,在第3厘米,7厘米,11厘米,17厘米,23厘米这五个位置上各有一只蚂蚁,木杆很细,不能同时通过两只蚂蚁,开始时,蚂蚁的头朝向左还是右是任意的,它们只会朝前走或掉头,但不会后退,当任意两只蚂蚁相遇后,蚂蚁会同时掉头朝反方向走,假设蚂蚁们每秒钟可以走1厘米的距离。编写程序(C/C++),求所有蚂蚁都离开木杆的最小时间和最大时间。(百度面试题)
读完这道题以后,我的想法是:
最短时间考虑如下:
首先标出木杆的中点,即在(0+27)/2=13.5厘米处。然后所有的蚂蚁都沿着木杆向离自己较近的一端走,这样所有蚂蚁都离开木杆的时间是最短的,即,为距离木杆中点最近的蚂蚁走向离它最近一端所用的时间。所以此题为11s。
<—— ——>
|________________|________________|
0 13.5 27
最长时间考虑如下:
要计算最长时间,就应该使最中间的那只蚂蚁尽量在木杆上来回走动。
情况1:
处在最中间的这只蚂蚁向右走,而所有其他蚂蚁都向木杆的中间方向走。这样最中间这只蚂蚁总共会调换4次方向,最后的方向仍然向是向右。经过计算,可知,中间蚂蚁的最后一次相遇是在13厘米处,而且前面总共走了3+2+3+2=10厘米,所以中间蚂蚁最后走出木杆总共走的距离为:10+(27-13)=24厘米,即,所用蚂蚁走出木杆所用时间为24s。
—>
|________________|________________|
0 11 13.5 27
情况2:
处在最中间的这只蚂蚁向左走,而所有其他蚂蚁都向木杆的中间方向走。这样最中间这只蚂蚁总共会调换4次方向,最后的方向仍然向是向左。经过计算,可知,中间蚂蚁的最后一次相遇也是在13厘米处(这是巧合),而且前面总共走了2+3+2+3=10厘米,所以中间蚂蚁最后走出木杆总共走的距离为:10+(13-0)=23厘米,即,所用蚂蚁走出木杆所用时间为23s。
<—
|________________|________________|
0 11 13.5 27
通过比较发现,处在最中间的这只蚂蚁向右走,而所有其他蚂蚁都向木杆的中间方向走,这种情况计算出的时间是最长的。
但是这样的计算是费时又费力的,是否还有更好的方法?
我们将此问题化简一下:
化简情况1:
木杆上只有一只蚂蚁,不妨设,它处在3厘米处。那么,
这只蚂蚁走出木杆的最短距离应该为3厘米,即用时3s。
这只蚂蚁走出木杆的最长距离应该为27-3=24厘米,即用时24s。
|________________|________________|
0 3 13.5 27
化简情况2:
木杆上只有两只蚂蚁,不妨设,它们分别处在3厘米处和11厘米处。那么,由于每只蚂蚁有两种可能(可以选择向右或向左),所以,这种情况总共有2^2=4种可能:都向右、都向左、一个向左一个向右、一个向右一个向左。我们只考虑相遇的情况。
这两只蚂蚁将会在(3+11)/2=7处相遇,不难计算得:
处在11厘米处的这只蚂蚁走出木杆的距离为4+(27-7)=24厘米,即用时24s。
处在3厘米处的这只蚂蚁走出木杆的距离为4+(7-0)=11厘米,即用时11s。
—> <—
|________________|________________|
0 3 11 13.5 27
我们可以发现,处在11厘米处的这只蚂蚁所走的距离可以转化为处在3厘米处的这只蚂蚁直接走向右端的距离(27-3=24)。
如果我们认真分析一下就能够发现,其实要计算所有蚂蚁走出木杆的时间,可以转化为计算处在离木杆一端最近的那只蚂蚁走向另一端所用的时间。
针对上面那道面试题,要计算最长时间,就可以根据这个结论直接得出答案:27-3=24厘米,即,用24s。
综上所述:
最短时间肯定是11s,位于11厘米处的蚂蚁怎么都不可能在低于11s的时间内离开木杆。
最长时间是24s,是位于3厘米处的蚂蚁从木杆的27CM处爬出。
结论是:不管木杆有多长,有多少只蚂蚁,最长的永远是(木杆长度-最靠近木杆边缘的蚂蚁的位置),最短的永远是(木杆最中间的蚂蚁的位置)。
#include <iostream>
#include <string>
#include <cmath>
using std::cout;
using std::endl;
#define SLEN 27
int getL(int ad)
{
return abs(SLEN-ad)>ad ? abs(SLEN-ad) : ad;
};
int getS(int ad)
{
return SLEN-getL(ad);
};
int main(void)
{
int ads[]={3,7,11,17,23};
int L=0,S=0; //L保存最长时间;S保存最短时间
for(int i=0;i<5;++i)
{
if (L<getL(ads[i])) L=getL(ads[i]);//这个是取最大值里面的那个最大值
if (S<getS(ads[i])) S=getS(ads[i]);//取每个蚂蚁的最短时间的最大值,因为最大的那个值决定了所有的蚂蚁都离开的最短时间
};
cout<<"最长所需"<<L<<"秒。/n最短所需"<<S<<"秒。"<<endl;
return 0;
}
/*
输出:
最长所需24秒。
最短所需11秒。
Press any key to continue
*/