过河到对面(动态规划)

题目:一天晚上,有n个人在桥的一边,他们需要过桥,过桥时每次不超过两人,他们只有一个手电筒,每次过桥后,需要有人把手电筒带回来,第i号人过桥的时间为a[i],两个人过桥的总时间为二者中时间长者,问所有人过完桥的总时间最短是多少?

输入格式:第一行输入一个整数n(1<=n<=1000),表示有n个人。

        第二行有n个整数ai, ai表示第i个人的过河所需要的时间(1<=ai<=1000)。

输出格式:输出一个整数,表示所有人过完河所需的时间。

思路:动态规划,设dp[n]表示n个人过完河所需的时间。(有最优子结构)

可以先将数组排序,过河时间最短的人在前面,即a[1].  过河有两种情况分析

1.倒着思考:当n个人过完河,手电筒也跟着过来了。所以当n-1人过完河时,手电筒也是跟着过来了。(花费时间最短时间dp[n-1])

   当桥边只剩一个人时,可以让花费时间最少的那个人a[1]过来送手电筒,人员n和人员1一同过河,花费时间为a[n]; 则dp[n]=dp[n-1]+a[n];

2.当桥边剩两个人时,即n-2人已经过河(时间为dp[n-2]),这样人员1先去送手电(时间a[1]),然后人员n和人员n-1同时过河,(时间为a[n]),然后人员2来送手电(时间为a[2]),然后人员1和人员2过桥(时间为a[2])  dp[n]=dp[n-2]+a[1]+2*a[2]+a[n];

最短时间:dp[n]=min( dp[n-1]+a[n] , dp[n-2]+a[1]+2*a[2]+a[n] );

 1 #include<vector>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int a[10010];
 7 int dp[10010];//dp[n]表示n个孩子过河需要的时间
 8 
 9 int main()
10 {
11     int n;
12     cin>>n;
13     for(int i=1;i<=n;i++){
14         cin>>a[i];
15     }
16     sort(a+1,a+n+1); 
17     dp[1]=a[1];
18     dp[2]=a[2];
19     for(int i=3;i<=n;i++){
20         dp[i]=min(dp[i-1]+a[0]+a[i],dp[i-2]+a[0]+2*a[1]+a[i]);
21     }
22     cout<<dp[n]<<endl;
23     return 0;
24 }

 

posted @ 2020-02-06 20:42  三行代码划江湖  阅读(880)  评论(0编辑  收藏  举报