题目链接;https://cn.vjudge.net/contest/319592#problem/E
题意:在一个夜黑风高的晚上,有n(n <= 50)个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不大于两人通过,他们只有一个手电筒,所以每次过桥的两个人需要把手电筒带回来,i号小朋友过桥的时间为T[i],两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。
参考https://blog.csdn.net/now_ing/article/details/78148715
我们先将所有人按花费时间递增进行排序,假设前i个人过河花费的最少时间为opt[i],那么考虑前i-1个人过河的情况,即河这边还有1个人,河那边有i-1个人,并且这时候手电筒肯定在对岸,所以opt[i] = opt[i-1] + a[1] + a[i] (让花费时间最少的人把手电筒送过来,然后和第i个人一起过河)
如果河这边还有两个人,一个是第i号,另外一个无所谓,河那边有i-2个人,并且手电筒肯定在对岸,所以opt[i] = opt[i-2] + a[1] + a[i] + 2a[2] (让花费时间最少的人把电筒送过来,然后第i个人和另外一个人一起过河,由于花费时间最少的人在这边,所以下一次送手电筒过来的一定是花费次少的,送过来后花费最少的和花费次少的一起过河,解决问题)
所以 opt[i] = min{opt[i-1] + a[1] + a[i] , opt[i-2] + a[1] + a[i] + 2a[2] }
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5+10;
ll a[maxn],dp[maxn];
int main()
{
int n;
cin>>n;
int i;
for(i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
memset(dp,0,sizeof(dp));
sort(a+1,a+1+n);
dp[0] = 0;
dp[1] = a[1];
dp[2] = max(a[1],a[2]);
for(i=3; i<=n; i++)
{
dp[i] = min(dp[i-1]+a[i]+a[1],dp[i-2]+a[i]+a[1]+2*a[2]);
}
printf("%lld\n",dp[n]);
return 0;
}