题目:
4个人在晚上过一座小桥,过桥时必须要用到手电筒,只有一枚手电筒,每次最多只可以有两人通过, 4个人的过桥速度分别为1分钟、2分钟、5分钟、10分钟,试问最少需要多长时间4人才可以全部通过小桥?
抽象:
N个人过桥,每个人过桥需要的时间为ti(1<=i<=N).每次最多两个人过桥,并且还要回来一个。求最快过桥时间。
输入:每人过桥时间数组,人数(数组元素个数)。
输出:最快时间。
解析:
最佳方案构造:以下是构造N个人(N≥1)过桥最佳方案的方法:
1) 如果N=1、2,所有人直接过桥。
2) 如果N=3,由最快的人往返一次把其他两人送过河。
3) 如果N≥4,设A、B为走得最快和次快的旅行者,过桥所需时间分别为a、b;
而Z、Y为走得最慢和次慢的旅行者,过桥所需时间分别为z、y。那么
当2b>a+y时,使用模式一将Z和Y移动过桥;
当2b<a+y时,使用模式二将Z和Y移动过桥;
当2b=a+y时,使用模式一将Z和Y移动过桥。
这两个模式是把最慢的两个人送过河,其他人原地不动最省时的两种可能的方法。
这样就使问题转变为N-2个旅行者的情形,从而递归解决之。
……
A Z →
A ←
A Y →
A ←
……
也就是“由A护送到对岸,A返回”,称作“模式一”。
模式一所用的时间是z+a+c+a
……
……
第n-2步: A B →
第n-1步: A ←
第n步: Y Z →
第n+1步: B ←
……
这个模式是“由A和B护送到对岸,A和B返回”,称作“模式二”。
模式二所用的时间是b+d+a+b
比较两个模式所使用的时间,便可得出:
当2b>a+y时,使用模式一将Z和Y移动过桥;
当2b<a+y时,使用模式二将Z和Y移动过桥;
当2b=a+y时,使用模式一将Z和Y移动过桥。
算法代码:
#include <vector>
int TravelBridge(std::vector<int> times)
{
// 假设时间数组已经排序
size_t length = times.size();
if(length <= 2)
return times[length-1];
else if(length == 3)
{
return times[0] + times[1] + times[2];
}
else
{
int totaltime = 0;
int a = times[0];
int b = times[1];
int z = times[length-1];
int y = times[length-2];
if(b*2 < a + y)
{
times.erase(times.end()-1);
times.erase(times.end()-1);
totaltime += b + a + z + b + TravelBridge(times);
}
else
{
times.erase(times.end()-1);
totaltime += z + a + TravelBridge(times);
}
return totaltime;
}
}
参考链接:http://blog.csdn.net/wcyoot/article/details/6428248