在一个夜黑风高的晚上,有n个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不超过两人通过,他们只有一个手电筒,所以每次过桥后,需要有人把手电筒带回来,第i号小朋友过桥的时间为ai,两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。
输入格式
第一行输入一个整数n(1≤n≤1000),表示有n个小朋友。
第二行有n个整数ai,ai表示第i个小朋友过河需要的时间(0<ai≤1000)。
输出格式
输出一个整数表示所有小朋友过河所需要的时间。
样例输入
4 1 2 5 10
样例输出
17
先考虑贪心,如果每次都让花费时间最少的人去送手电的话,样例答案就应该是19,但是实际答案应该是17,故不能一直让花费时间最少的人去送手电。
样例的具体步骤是这样的:
第一步:1和2过去,花费时间2,然后1回来(花费时间1);
第二歩:3和4过去,花费时间10,然后2回来(花费时间2);
第三步:1和2过去,花费时间2,总耗时17。
我们先将所有人按花费时间递增进行排序,假设前i个人过河花费的最少时间为dp[i]。
那么考虑前i-1个人过河的情况,即河这边还有1个人,河那边有i-1个人,并且这时候手电筒肯定在对岸,所以dp[i] = dp[i-1] + a[1] + a[i] (让花费时间最少的人把手电筒送过来,然后和第i个人一起过河)
如果河这边还有两个人,一个是第i号,另外一个无所谓,河那边有i-2个人,并且手电筒肯定在对岸,所以dp[i] = dp[i-2] + a[1] + a[i] + 2*a[2] (让花费时间最少的人把电筒送过来,然后第i个人和另外一个人一起过河,由于花费时间最少的人在这边,所以下一次送手电筒过来的一定是花费次少的,送过来后花费最少的和花费次少的一起过河,解决问题)
所以 dp[i] = min{dp[i-1] + a[1] + a[i] , dp[i-2] + a[1] + a[i] + 2*a[2] }
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 using namespace std; 16 17 int a[1010]; 18 int dp[1010]; 19 20 int main() 21 { 22 int n; 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++) 25 scanf("%d",&a[i]); 26 sort(a+1,a+1+n); 27 dp[1]=a[1]; dp[2]=a[2]; 28 for(int i=3;i<=n;i++) 29 { 30 dp[i]=min(dp[i-1]+a[1]+a[i],dp[i-2]+a[1]+a[i]+2*a[2]); 31 } 32 printf("%d ",dp[n]); 33 return 0; 34 }
-