动态规划——小朋友过河

动态规划——小朋友过河

本Markdown编辑器使用[StackEdit][6]修改而来,用它写博客,将会带来全新的体验哦:

小朋友过桥问题:在一个夜黑风高的晚上,有n(n <= 50)个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不大于两人通过,他们只有一个手电筒,所以每次过桥的两个人需要把手电筒带回来,i号小朋友过桥的时间为T[i],两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。

问题分析:首先将n个小朋友按过河时间从小到大排序,设第i个小朋友过河的时间为T[i]。假设n个小朋友过河的总时间为f(n),则f(1)=T[1]; f(2)=T[2];f(3)=T[2]+T[1]+T[3]。
当n=4时,
1,2号小朋友过河,时间为T[2]
1号小朋友回来,时间为T[1]
3,4号小朋友过河,时间为T[4]
2号小朋友回来,时间为T[2]
此时,河这边仅有1,2号小朋友,时间为f(2)
所以过河总时间f(4) =T[2]+T[1]+T[4]+T[2]+f(2)

假设有n个小朋友(n>=4):
1,2号小朋友过河,时间为T[2]
1号小朋友回来,时间为T[1]
n-1,n号小朋友过河,时间为T[n]
2号小朋友回来,时间为T[2]
此时,河这边有1号到n-2号的所有小朋友,所以时间为f(n-2)
所以过河总时间f(n) =T[2]+T[1]+T[n]+T[2]+f(n-2)

通过以上表述我们可以得到如下递推公式:
f(1)=T[1]
f(2)=T[2]
f(3)=T[1] + T[2] + T[3]
f(n) = T[1]+2T[2]+T[n] + f(n-2); n>=4

实现代码如下:

#include <iostream>
#include <algorithm>
using namespace std;

int baby_cross_river(int *T, int n)
{
    if(n<=2) return T[n];
    if(n == 3) return T[1]+T[2]+T[3];
    int f_n2 = T[2]; //f(n-2)
    int f_n1 = T[1]+T[2]+T[3];//f(n-1)
    int f_n = 0;
    for(int i = 4; i <= n; ++i)
    {
        f_n = T[1] + 2*T[2] + T[i] + f_n2;
        f_n2 = f_n1;
        f_n1 = f_n;
    }
    return f_n;
}
int main()
{
    const int n = 5;
    int T[n+1]={0, 1, 2, 5, 10, 20};//start index = 1
    int fn = baby_cross_river(T, n);
    cout<<"total cost is "<<fn<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Gang_dada/article/details/81167535