zoukankan      html  css  js  c++  java
  • 计蒜客 蓝桥杯模拟 快速过河

     

    在一个夜黑风高的晚上,有 nn 个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不超过两人通过,他们只有一个手电筒,所以每次过桥后,需要有人把手电筒带回来,第 ii 号小朋友过桥的时间为 a_iai,两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。

    输入格式

    第一行输入一个整数 nn,表示有 nn 个小朋友。

    第二行有 nn 个整数 a_iai ,a_iai 表示第 ii 个小朋友过河需要的时间。

    输出格式

    输出一个整数,表示所有小朋友过河所需要的时间。

    随后是你的通过和返回次序,每一行是两个或者三个整数,第一个整数,表示这一行有几个整数,后面的一个或者两个整数对应着人(通过时间代表人),返回也要占一行。

    数据范围

    对于 30\%30% 的数据:1 le n le 51n5。

    对于 100\%100% 的数据:1 le n le 10001n1000 ,0 < a_i le 10000<ai1000

    样例解释

    1717 秒

    (1,2)(1,222 秒

    (1)(111 秒

    (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
    ",dp[n-1]);
        n --;
        while( 1 ) {
            if( !n ) {
                sum += a[0];
                printf("1 %lld
    ",a[0]);
                break;
            } else if( n == 1 ) {
                sum += a[1];
                printf("2 %lld %lld
    ",a[0],a[1]);
                break;
            } else if( n == 2 ) {
                sum += a[0] + a[1] + a[2];
                printf("2 %lld %lld
    ",a[0],a[1]);
                printf("1 %lld
    ",a[0]);
                printf("2 %lld %lld
    ",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
    ",a[0],a[1]);
                    printf("1 %lld
    ",a[0]);
                    printf("2 %lld %lld
    ",a[n-1],a[n]);
                    printf("1 %lld
    ",a[1]);
                    n -= 2;
                } else {
                    sum += a[0] + a[n];
                    printf("2 %lld %lld
    ",a[0],a[n]);
                    printf("1 %lld
    ",a[0]);
                    n -= 1;
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Elementary Methods in Number Theory Exercise 1.2.25
    Elementary Methods in Number Theory Exercise 1.2.14
    图解欧几里德算法
    图解欧几里德算法
    Elementary Methods in Number Theory Exercise 1.2.14
    Android中的长度单位详解(dp、sp、px、in、pt、mm)
    分享下多年积累的对JAVA程序员成长之路的总结
    android异常之都是deamon惹的祸The connection to adb is down, and a severe error has occured.
    TomatoCartv1.1.8.2部署时报错
    JavaScript浏览器对象之二Document对象
  • 原文地址:https://www.cnblogs.com/l609929321/p/10563497.html
Copyright © 2011-2022 走看看