解题思路
有 N 个人需要渡河,有一条船,船上最多只能乘坐两人。第 i 个人一个人划船到对面需要 T[i-1] 时间。
为了保证船的平衡,当船上有两人时,需按照慢的那个人的速度划船,也就是说船到达对岸的时间等于船上渡河时间长的那个人的时间。
求所有人过河的花费时间最少为多少?
首先将 N 个人按照渡河时间从小到大排序,则第 1 个人和第 2 个人可以作为来回划船的人。
dp[i] 表示前 i+1 个人过河花费的最少的总时间。dp[0] = T[0],表示1 个人过河时间。dp[1] = T[1],两个人一起划到对岸。dp[i] = min(dp[i-1]+T[0]+T[i], dp[i-2]+T[0]+T[i]+T[1]+T[1])。
前 i 个人渡河时间为 dp[i-1],还有 1 人需要渡河,由第 1 个人花费 T[0] 时间接第 i+1 个人,两人渡河时间为 T[i]。
此时,dp[i] = dp[i-1] + T[0] + T[i]。
前 i-1 个人渡河时间为 dp[i-2],还有两个人需要渡河,由第 1 个人花费 T[0] 时间划船回来,第 i 个人和第 i+1 个人一起过河花费时间为 T[i],再由第 2 个人将船划回来,时间为 T[1],和第 1 个人一起渡河,时间为 T[1]。
此时,dp[i] = dp[i-2] + T[0] + T[i] + T[1] + T[1]。
取两种方案的较小值。最后 dp[n-1] 是结果。
C++代码
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int N;
scanf("%d", &N);
vector<int> T(N);
for(int i=0; i<N; ++i){
scanf("%d", &T[i]);
}
sort(T.begin(), T.end());
vector<int> dp(N, 0);
dp[0] = T[0];
dp[1] = T[1];
for(int i=2; i<N; ++i){
dp[i] = min(dp[i-1]+T[0]+T[i], dp[i-2]+T[0]+T[i]+T[1]+T[1]);
}
printf("%d\n", dp[N-1]);
return 0;
}
京公网安备 11010502036488号