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 过河问题的主要内容,如果未能解决你的问题,请参考以下文章