POJ 1700 Crossing River 过河问题 贪心法

来源:互联网 发布:阿里云合作伙伴 logo 编辑:程序博客网 时间:2024/05/21 20:02

Crossing River
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 13622 Accepted: 5211

Description

A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arrangement must be arranged in order to row the boat back and forth so that all people may cross. Each person has a different rowing speed; the speed of a couple is determined by the speed of the slower one. Your job is to determine a strategy that minimizes the time for these people to get across.

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains N, and the second line contains N integers giving the time for each people to cross the river. Each case is preceded by a blank line. There won't be more than 1000 people and nobody takes more than 100 seconds to cross.

Output

For each test case, print a line containing the total number of seconds required for all the N people to cross the river.

Sample Input

141 2 5 10

Sample Output

17

Source

POJ Monthly--2004.07.18

    题意:过河问题。

    分析:转自:http://blog.csdn.net/SamanthaC_/article/details/52781039

题意是:N个人过河,但只有一只船,船不能载多于2个人,每个人划船的时间都不一样,求所有人都渡过河所需的最短时间。注意:船要划回来。思路:先将每个人的划船时间降序排列,然后当:
(1)N=1, 最短时间为a[0];
(2)N=2,最短时间为a[1];
(3)N=3,最短时间为a[0]+a[1]+a[2];
(4)N>=4,此时不妨把问题分解为单个来回来讨论,每个来回都贪心一下,而每趟主要任务是如何最快地把最慢的两个人送到对岸,现在设最快的人为A,次快的人为B ,次慢的人为C,最慢的人为D,则有两种方案:
1. A先后送C、D过河后,把船划回来。此方案耗时为:2*a[0]+a[N-2]+a[N-1];
2. A、B先过河,A把船划回来,然后C、D过河,在对岸的B把船划回来。此方案耗时为:a[0]+2*a[1]+a[N-1]。
每个来回都送走2个,所以N-2,当N<=3时,便是上面三种情况。
    AC代码:

#include<stdio.h>#include<algorithm>using namespace std;const int maxn=1005;int a[maxn];int main(){int T;scanf("%d",&T);while(T--){int n;scanf("%d",&n);for(int i=0; i<n; i++)scanf("%d",&a[i]);sort(a,a+n);//顺序排列long long res=0;int i;for(i=n-1; i>2; i-=2)//每次将最慢的和次慢的运送到河对岸 存在 两种方法res+=min(a[0]+2*a[1]+a[i],2*a[0]+a[i-1]+a[i]);//选择其中的较小者if(i==2)//此状态下有三个元素没有过河  直接算出结果即可  res+=a[0]+a[1]+a[2];else if(i==1)//此状态下只有第一个元素和第二个元素没有过河 res+=a[1];else res+=a[0];//此状态下只有第一个元素没有过河 printf("%lld\n",res);}}

    特记下,以备后日回顾。

1 0