解题思路

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;
}