//https://blog.youkuaiyun.com/u013309870/article/details/75193592 例1
【例题1】在一个夜黑风高的晚上,有n(n <= 50)个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不大于两人通过,他们只有一个手电筒,所以每次过桥的两个人需要把手电筒带回来,i号小朋友过桥的时间为T[i],两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。
下面是源码,无解析!
提示几点:对于递归这种,大家脑海中想象成一个完全二叉树就好,递归就是把所有的结果和方案都过一遍
备忘录(常用于自顶向下把)就是,
记录最底层的已经解析的结果,然后使 函数回溯时能够提前结束递归。
#include <algorithm>
//过桥所需的时间How long time spend crossing the bridge
const int Times[]={1,2,5,10,7,9};
//自底向上的方法
int crossBridgeDownToUp(const int *Times, int n)
{
//排序Times,此处省略
int * costTime = new int[n];
costTime[0] = Times[0];
costTime[1] = Times[1];
if (n <= 2)
{
return Times[n-1];
}
else{
for (int i = 2; i<n; ++i)
{
costTime[i]=min(costTime[i-1] + Times[0] + Times[i],
Times[0] + 2 * Times[1] + Times[i] + costTime[i-2]);
}
return costTime[n-1];
}
}
//自顶向下的方法
int crossBridgeUpToDown(int n)
{
//排序Times,此处省略
//记录结果
if (n <= 2)
{
return Times[n-1];
}
return min(crossBridgeUpToDown(n-1) + Times[0] + Times[n-1],
Times[0] + 2 * Times[1] + Times[n-1] + crossBridgeUpToDown(n-2));
}
//带备忘录式的自顶向下方法
int memoCrossBridge(int n, int *memoCostTime)
{
//排序Times,此处省略
if(memoCostTime[n-1] >= 0)
{
return memoCostTime[n-1];
}
//记录结果
if (n <= 2)
{
memoCostTime[n-1] = Times[n-1];
return Times[n-1];
}
memoCostTime[n-1] = min(memoCrossBridge(n-1,memoCostTime) + Times[0] + Times[n-1],
Times[0] + 2 * Times[1] + Times[n-1] + memoCrossBridge(n-2,memoCostTime));
return memoCostTime[n-1];
}
//备忘录式的方法
int record(int n)
{
int *memoCostTime = new int [n];
for (int i = 0; i < n; i++)
{
memoCostTime[i] = -1;
}
return memoCrossBridge(n, memoCostTime);
}
int main() {
std::cout << "备忘录式的方法:" << record(4);
}