Crossing River(POJ1700)

来源:互联网 发布:丹尼格林13总决赛数据 编辑:程序博客网 时间:2024/05/16 03:57

在文章贪心详解中第二种类型也有此题目

Crossing River(POJ1700)

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

1
4
1 2 5 10

Sample Output

17
一道英文题,不过翻译很简单,还是简单翻译一下:
只有一艘船,能乘2人,船的运行速度为2人中较慢一人的速度,过去后还需一个人把船划回来,问把n个人运到对岸,最少需要多久。这里需要注意的是,人到了对岸并没走,也就是开船回来的不一定是坐船去的那两个人中的其中一个。


题解:我们考虑如何才能把最不利的因素消除,让最有利的因素更多的发挥,然而此处可知,最不利的肯定是消不了的,因为时间是按最慢的算的,所以我们去消除次最不利的因素,所以我们先把最慢的和次最慢的送到对岸,回来的时候选择最快的方案,那么和这个次最慢的一起坐船的是谁呢?有两个选择,我们来讨论下:
一:这个思路的意思也就是,我让回来的时间最少应该就是时间最短的时间,毕竟去的时候时间怎么也是按慢的时间算的,这样我们很容易就可以想出下一步我们该怎么做,最快的回来再跟最慢的回去就行了。
二:最慢的和他一起,第二次我们可以让最快的和次最快的一起去,,然后让他俩把俩船再开回来这个思路其实也很有道理,既然最慢的怎么也得过去,那我让次最慢的跟他一起岂不少了很多时间,第一种两次过河一次是最慢的一次是次最慢的,第二种方法是一次最慢的一次是此快的大大节省过河时间。
这么一分析貌似第二个更高大上,更像正确答案,但并不是,因为这每个时间的差距是不一定的,第二种回去的时间一次是最快的,可另一次是此最快的,我们写出他们的时间(从小到大排好序后)
一:t[0]+t[n-1]+t[0]+t[n-2]
二:t[0]+t[n-1]+2*t[1]
我们可以看到他们之间的区别是2*t[1]和t[n-2]+t[0];
这两者并不能明确判断哪个大,所以我们每次选择方案时还是需要比较一番的。
下面我们上代码:

CODE:

#include <iostream>#include <algorithm>#include <stdio.h>using namespace std;int main(){    int a[1000],t,n,sum;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        sum=0;        for(int i=0;i<n;i++)             scanf("%d",&a[i]);        while(n>3)        {            sum+=min(2*a[1]+a[0]+a[n-1],2*a[0]+a[n-1]+a[n-2]);            n-=2;        }        if(n==3) sum+=a[0]+a[1]+a[2];        else if(n==2) sum+=a[1];        else sum+=a[0];        printf("%d\n",sum);    }}
原创粉丝点击