初看到蚂蚁爬杆的问题是在编程之美上看到的,看到的大部分是对所有蚂蚁走出杆所需要的最短最长时间的求解,在编程之美上还有很多扩展问题。
其中的一个扩展问题是第i个蚂蚁什么时候走出木杆?
解题的关键在蚂蚁的速度是相同的,所以相遇后各自调头走转换成相遇后交换一下相遇者的名字,而不调头继续走的效果是一样的。不要让相遇后各自调头,调乱了。
假如开始时蚂蚁A 向左走,它前面没有蚂蚁或是前面的蚂蚁都向左走那么不存在相遇,或是追上的问题,也就不用调头,算他的走出时间很明显;如果蚂蚁A的前面有一只蚂蚁B向右走,那么他们一定会相遇,按题目要求两只蚂蚁在相遇时各自调头,也就是蚂蚁A向右走,蚂蚁B向左走。若是这样的一直调头的去计算很容易乱。找到他们速度相同这个突破点。假设A和B在经历时间 t 1 后相遇,相遇后蚂蚁A调头,现在向右走,A向右走 时间 t2 后走出木杆或是遇到下一个蚂蚁C,那么蚂蚁A从开始走到走出木杆或是遇到蚂蚁C经历的时间是t1+t2,如果蚂蚁B在遇到蚂蚁A后没有调头继续向右走那么他也会在走 时间 t2后走出木杆或是遇到蚂蚁C。所以蚂蚁A走出木杆或是遇到蚂蚁C的时间等于蚂蚁B从他起点一直向右走,走出木杆所需要的时间或是遇到蚂蚁C的时间。
所以把相遇后各自调头转换成相遇后交换一下彼此的名字,也就是说,A向左走,B向右走且B在A的前面那么在他们相遇后,不让他们调头,而把A的名字改成B,B的名字改成A,继续朝着自己的方向走。定义一个数据结构
struct Ant
{
bool mdirection;//0,向左,1,向右
int Name;//原名
int tempName;//别名在两个蚂蚁相遇时交换彼此的别名
}
要求的是第i 个蚂蚁什么时候走出木杆。
这里以“0”表示蚂蚁向左走;“1”表示蚂蚁向右走。
假设开始时有这么一组状态,还以杆长27,蚂蚁速度为1,为例。
原名 | 1 | 2 | 3 | 4 | 5 |
方向 | 1 | 1 | 1 | 0 | 1 |
别名 | 1 | 2 | 3 | 4 | 5 |
起始位置 | 3 | 7 | 11 | 17 | 23 |
起始位置为别名的起始位置
现在求“蚂蚁4”走出杆的时间,
1:“蚂蚁4”向左走那么他会遇到“蚂蚁3”按照交换信息的思路,交换信息
原名 | 1 | 2 | 3 | 4 | 5 |
方向 | 1 | 1 | 0 | 1 | 1 |
别名 | 1 | 2 | 4 | 3 | 5 |
起始位置 | 3 | 7 | 17 | 11 | 23 |
2:“这时蚂蚁4”向右走,“蚂蚁5”向右走他们不用再交换信息,可以直接走出,所以“蚂蚁4”走出的时间是(27-11)/1。
再从起始状态来分析“蚂蚁2”的走出状态变化
1:“蚂蚁2”向右走从他的前面有“蚂蚁4”向左走,和蚂蚁3向右走,则“蚂蚁4”和“蚂蚁3”先交换信息
原名 | 1 | 2 | 3 | 4 | 5 |
方向 | 1 | 1 | 0 | 1 | 1 |
别名 | 1 | 2 | 4 | 3 | 5 |
起始位置 | 3 | 7 | 17 | 11 | 23 |
2:“蚂蚁2”在于“蚂蚁3”交换信息
原名 | 1 | 2 | 3 | 4 | 5 |
方向 | 1 | 0 | 1 | 1 | 1 |
别名 | 1 | 4 | 2 | 3 | 5 |
起始位置 | 3 | 17 | 7 | 11 | 23 |
3:“蚂蚁2”现在向左走,他前面有“蚂蚁1”向右走,他们交换信息
原名 | 1 | 2 | 3 | 4 | 5 |
方向 | 0 | 1 | 1 | 1 | 1 |
别名 | 4 | 1 | 2 | 3 | 5 |
起始位置 | 17 | 3 | 7 | 11 | 23 |
4:“蚂蚁2”现在向右走他前面的蚂蚁都向右走那么,他可以走出杆,t=(27-3)/1。
求第i个蚂蚁走出杆的时间的问题,转换为求“蚂蚁i”的前面没有一个蚂蚁和他走的方向相反时的状态。
自己是这么理解和想的,不知道说明白没。
(有错误的地方,还望各位指正。)