Laoj P1283 过河问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laoj P1283 过河问题相关的知识,希望对你有一定的参考价值。

试题描述
在一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸。而东岸边有一条小船。
船太小了,一次只能乘坐两人,每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较长的人所用的时间。
现在已知N个人的渡河时间T,Oliver想要你告诉他,他们最少要花费多少时间,才能使所有人都过河。
注意,只有船在东岸(西岸)时东岸(西岸)的人才能坐上船划到对岸。

输入格式
输入文件第一行为人数N,以下有N行,每行一个数。

第i+1行的数为第i个人的渡河时间。
输出格式
 输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间。
输入示例
4
6
7
10
15

输出示例
42

【样例解释】
初始:东岸(1,2,3,4),西岸()
第一次:东岸(3,4),西岸(1,2),时间7
第二次:东岸(1,3,4),西岸(2),时间6
第三次:东岸(1),西岸(2,3,4),时间15
第四次:东岸(1,2),西岸(3,4),时间7
第五次:东岸(),西岸(1,2,3,4),时间7
所以总时间为7+6+15+7+7=42,没有比这个更优的方案
注释说明
对于40%的数据满足N≤8
对于100%的数据满足N≤100000

 

 

【分析】

USACO刷不下去于是来Laoj找道题做..

这种类型似乎叫贪心dp,每次都只考虑最好的方案,先把数组排序,首先在n=0,1,2,3时都可以特判,然后再每次考虑两个人的过河最佳方案,因为过河时间与慢的人有关,所以每次送船都选择1号来送,比如对于第i个人,最佳的方案可能是1和i一起过去,1把船送回来,1再和i-1一起过去,最后再由1把船送回来,总代价是t[i]+t[i-1]+t[1]*2。也有可能是两个较慢的人一起过河,则首先1和2一起过河,1把船送回来,然后i和i-1一起过河,2把船送回来,总代价为t[i]+t[2]*2+t[1]。每次在这两个方案中选最佳的即可。

 

【代码】

#include <bits/stdc++.h>
using namespace std;

int read() {//读入优化
    int x=0, w=1;
    char ch=0;
    while (ch<0 || ch>9) {
        ch=getchar();
        if (ch==-)
            w=-1;
    }
    while (ch>=0 && ch<=9)
        x=(x<<3)+(x<<1)+ch-0, ch=getchar();
    return x*w;
}

int n, t[100005], dp[100005];

int main() {
    cin >> n;
    for (int i=1;i<=n;++i)
        t[i]=read();
    sort(t+1, t+n+1);
    if (n==0) {//一些特判
        printf("0\n");
        return 0;
    }
    if (n==1) {
        printf("%d\n", t[1]);
        return 0;
    }
    if (n==2) {
        printf("%d\n", t[1]+t[2]);
        return 0;
    }
    if (n==3) {
        printf("%d\n", t[1]+t[2]+t[3]);
        return 0;
    }
    dp[2]=t[2], dp[3]=t[1]+t[2]+t[3];//初始化
    for (int i=4;i<=n;++i)
        dp[i]=dp[i-2]+min(t[i]+t[i-1]+t[1]*2, t[i]+t[1]+t[2]*2);//每次选择最佳方案
    printf("%d\n", dp[n]);
}

 

以上是关于Laoj P1283 过河问题的主要内容,如果未能解决你的问题,请参考以下文章

P1283 平板涂色

P1283 平板涂色

Laoj P1272 取数

Laoj P1197 简单的方格取数

Laoj P1288 最小乘车费用

Laoj P1271 复制书稿