过桥问题(动态规划)

过桥问题(动态规划)

题目:4人过桥,ABCD要单独过桥分别需要用时1分、2分、5分、10分,桥最多只能承受2人重量,由于天黑,每次过桥时需要一个手电筒,4人中只有一个手电筒,求如何在17分钟之内全部过桥。

思路:网上搜了一下,是一个典型的贪心算法,贪心策略有两种,对应着动态规划中状态转移方程的两个状态,每次取最小时间的贪心策略就是最后的结果。

方案一:假设第i个人要过桥,由对岸最快的a[0]回来传手电筒(+a[0]),并和a[i]一起回对岸(+a[i])。

方案二:假设第i个人和第i-1个人一起过桥,因为过桥时间是取两人中的最长时间(有点像木桶的短板效应),所以过桥时间相近的人一起过桥时间损耗可能会比方案一的少,第一步仍然是由对岸最快的a[0]回来传手电筒(+a[0]),将手电筒给第i人和第i-1人,让他们一起过桥(+a[i]),然后由对岸次快的a[1]回来接a[0]重新回到对岸(+2a[i])。

容易知道3个人以下的初始最短过桥时间分别为

dp[0]=a[0],

dp[1]=a[1],

dp[2]=a[0]+a[1]+a[2];//a[0]和a[1]一起过桥,再由a[0]回来送手电筒,接送a[2]过桥。

#include

#include

#include

#include

#include

#include

#include

using namespace std;

typedef long long ll;

ll dp[10000];//前i个人过桥所需的最短时间dp[i]

ll a[10000];//a[i]为第i个人过桥所需时间

int main()

{

int n;//总共有n人需要过桥

cin >> n;

for (int i = 0;i < n;i++)

{

cin >> a[i];

}

sort(a, a + n);//对n个人过桥的时间从小到大排序

dp[0] = a[0];

dp[1] = a[1];

dp[2] = a[0] + a[1] + a[2];//三个人以下过桥的初始最短时间

for (int i = 3;i < n;i++)

{

dp[i] = min(dp[i - 1] + a[0] + a[i], dp[i - 2] + a[0] + 2*a[1] + a[i]);//方案一:假设第i个人要过桥,由对岸最快的a[0]回来传手电筒(+a[0]),并和a[i]一起回对岸(+a[i])

//方案二:假设第i个人和第i-1个人一起过桥,因为过桥时间是取两人中的最长时间(有点像木桶的短板效应),所以过桥时间相近的人一起过桥时间损耗可能会比方案一的少,第一步仍然是由对岸最快的a[0]回来传手电筒(+a[0]),将手电筒给第i人和第i-1人,让他们一起过桥(+a[i]),然后由对岸次快的a[1]回来接a[0]重新回到对岸(+2a[i])

}

cout << dp[n - 1];

}

得到的结果正好为17

相关文章

剔的组词、含义
365网络股份有限公司总部

剔的组词、含义

📅 10-16 👁️ 6760
lol如何使用自制皮肤
bt365在线

lol如何使用自制皮肤

📅 06-27 👁️ 7170
三门峡到郑州的1152途经哪些站?
365网络股份有限公司总部

三门峡到郑州的1152途经哪些站?

📅 10-09 👁️ 2423