在一個夜黑風高的晚上,有 nn 個小朋友在橋的這邊,如今他們須要過橋,可是因爲橋很窄,每次只容許不超過兩人經過,他們只有一個手電筒,因此每次過橋後,須要有人把手電筒帶回來,第 ii 號小朋友過橋的時間爲 a_iai,兩我的過橋的總時間爲兩者中時間長者。問全部小朋友過橋的總時間最短是多少。html
第一行輸入一個整數 nn,表示有 nn 個小朋友。ios
第二行有 nn 個整數 a_iai ,a_iai 表示第 ii 個小朋友過河須要的時間。ide
輸出一個整數,表示全部小朋友過河所須要的時間。ui
隨後是你的經過和返回次序,每一行是兩個或者三個整數,第一個整數,表示這一行有幾個整數,後面的一個或者兩個整數對應着人(經過時間表明人),返回也要佔一行。spa
對於 30\%30% 的數據:1 \le n \le 51≤n≤5。debug
對於 100\%100% 的數據:1 \le n \le 10001≤n≤1000 ,0 < a_i \le 10000<ai≤1000htm
1717 秒blog
(1,2)(1,2) 22 秒排序
(1)(1) 11 秒ip
(5,10)(5,10) 1010 秒
(2)(2) 22 秒
(1,2)(1,2) 22 秒
4 1 2 5 10
17 2 1 2 1 1 2 5 10 1 2 2 1 2
題解:
動態規劃:
咱們先將全部人按花費時間遞增進行排序,假設前 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] + 2*a[2](讓花費時間最少的人把
電筒送過來,而後第i我的和另一我的一塊兒過河,因爲花費時間最少的人在這邊,因此下
一次送手電筒過來的必定是花費次少的,送過來後花費最少的和花費次少的一塊兒過河,解決
問題),因此 opt[i] = min(opt[i-1]+a[1]+a[i],opt[i-2]+a[1]+a[i]+2*a[2])
貪心:
一我的:時間爲a0 。
兩我的:時間爲a1。
三我的:時間爲a0+a1+a2 。
多我的:比較下面兩種方案中的最優值。
a[0]*2+a[n]+a[n-1] ? a[0]+2*a[1]+a[n]
#include <map> #include <set> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <vector> #include <string> #include <bitset> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define ls (r<<1) #define rs (r<<1|1) #define debug(a) cout << #a << " " << a << endl using namespace std; typedef long long ll; const ll maxn = 1e5+10; const ll mod = 1e9+7; const double pi = acos(-1.0); const double eps = 1e-8; ll n, sum = 0, a[maxn], dp[maxn]; int main() { scanf("%lld",&n); for( ll i = 0; i < n; i ++ ) { scanf("%lld",&a[i]); } sort(a,a+n); dp[0] = a[0]; dp[1] = a[1]; for( ll i = 2; i < n; i ++ ) { dp[i] = min( dp[i-1]+a[0]+a[i], dp[i-2]+a[0]+2*a[1]+a[i] ); } printf("%lld\n",dp[n-1]); n --; while( 1 ) { if( !n ) { sum += a[0]; printf("1 %lld\n",a[0]); break; } else if( n == 1 ) { sum += a[1]; printf("2 %lld %lld\n",a[0],a[1]); break; } else if( n == 2 ) { sum += a[0] + a[1] + a[2]; printf("2 %lld %lld\n",a[0],a[1]); printf("1 %lld\n",a[0]); printf("2 %lld %lld\n",a[0],a[2]); break; } else { if( a[0]*2+a[n]+a[n-1]>a[0]+2*a[1]+a[n] ) { sum += a[0]+2*a[1]+a[n]; printf("2 %lld %lld\n",a[0],a[1]); printf("1 %lld\n",a[0]); printf("2 %lld %lld\n",a[n-1],a[n]); printf("1 %lld\n",a[1]); n -= 2; } else { sum += a[0] + a[n]; printf("2 %lld %lld\n",a[0],a[n]); printf("1 %lld\n",a[0]); n -= 1; } } } return 0; }