过河到对面(动态规划)
题目:一天晚上,有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 }