計蒜客 藍橋杯模擬 快速過河

 

在一個夜黑風高的晚上,有 nn 個小朋友在橋的這邊,如今他們須要過橋,可是因爲橋很窄,每次只容許不超過兩人經過,他們只有一個手電筒,因此每次過橋後,須要有人把手電筒帶回來,第 ii 號小朋友過橋的時間爲 a_iai,兩我的過橋的總時間爲兩者中時間長者。問全部小朋友過橋的總時間最短是多少。html

輸入格式

第一行輸入一個整數 nn,表示有 nn 個小朋友。ios

第二行有 nn 個整數 a_iai ,a_iai 表示第 ii 個小朋友過河須要的時間。ide

輸出格式

輸出一個整數,表示全部小朋友過河所須要的時間。ui

隨後是你的經過和返回次序,每一行是兩個或者三個整數,第一個整數,表示這一行有幾個整數,後面的一個或者兩個整數對應着人(經過時間表明人),返回也要佔一行。spa

數據範圍

對於 30\%30% 的數據:1 \le n \le 51n5。debug

對於 100\%100% 的數據:1 \le n \le 10001n1000 ,0 < a_i \le 10000<ai1000htm

樣例解釋

1717 秒blog

(1,2)(1,222 秒排序

(1)(111 秒ip

(5,10)(5,101010 秒

(2)(222 秒

(1,2)(1,222 秒

本題答案不惟一,符合要求的答案均正確

樣例輸入

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;
}
相關文章
相關標籤/搜索