計蒜客 藍橋杯模擬 快速過河—dp
題目描述:
在一個夜黑風高的晚上,有 nn 個小朋友在橋的這邊,現在他們需要過橋,但是由於橋很窄,每次只允許不超過兩人通過,他們只有一個手電筒,所以每次過橋後,需要有人把手電筒帶回來,第 ii 號小朋友過橋的時間爲 a_iai,兩個人過橋的總時間爲二者中時間長者。問所有小朋友過橋的總時間最短是多少。
輸入格式
第一行輸入一個整數 nn,表示有 nn 個小朋友。
第二行有 nn 個整數 a_iai ,a_iai 表示第 ii 個小朋友過河需要的時間。
輸出格式
輸出一個整數,表示所有小朋友過河所需要的最短時間。
解題思路:
我們定義dp[i]:代表一共有i個人的話,需要花費的最少時間。
首先給數組升序(其中,a[1]是數組的第一個元素),假設現在一共有i個人,那麼可以分爲兩種情況:
(1)沒有過河的人是第i-1個人,和第i個人兩個人【已經有i-2個人已經過河了】:dp[i]=dp[i-2]+a[1]+a[i]+2*a[2];(在dp[i-2]的基礎之上,加上第一個人回來送手電筒的時間【a[1]】+第i-1和第i個人拿着手電筒過河的時間【a[i]】+第2個人回去送手電筒【a[1]】+第1個人和第2個人一起過河的時間【a[2]】)
(2)沒有過河的人是第i個人【已經有i-1個人已經過河了】:dp[i]=dp[i-1]+a[1]+a[i];(在dp[i-1]的基礎之上,加上第一個人回來送手電筒的時間【a[1]】+第1個人和第i個人一起過河的時間【a[i]】)
AC代碼:
//過河
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
#define min(a,b) a<b?a:b;
using namespace std;
int a[1010];
int dp[1010];
int main()
{
int n,i;
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
//dp[i]:代表一共有i個人的話,需要花費的最少時間
dp[1]=a[1];
dp[2]=a[2];
dp[3]=a[1]+a[2]+a[3];
for(i=4;i<=n;i++)
{
dp[i]=min(dp[i-1]+a[1]+a[i],dp[i-2]+a[1]+a[i]+2*a[2]);
}
cout<<dp[n]<<endl;
return 0;
}