POJ1700 Crossing River(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 13301          Accepted: 5087

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

 

一、题目大意

      有N个人要渡河,但是只有一艘船,船上每次最多只能载两个人,渡河的速度由两个人中较慢的那个决定,小船来回载人直到所有人都渡河,求最短的渡河时间。

 

二、解题思路

      一开始的时候忘了需要有一个人将小船撑回起点,所以简单的对N个人进行排序,从小到大两个人为一组,依次渡河,显然答案是错误的。习惯性眼瞎是病得治QAQ。假如考虑需要回程的情况,那么每一次都需要让在终点渡河最快的人把船撑回,所以需要保证终点有速度快的人能够把船撑回起点,显然一开始的思路时间不是最短。假设有速度最快的人a、速度次快的人b,速度最慢的人c,速度次慢的人d,把c和d送到终点考虑两种策略

▶1、 a和b出发,a回来,c和d出发,b回来

▶2、 a和c出发,a回来,a和d出发,a回来

只需要比较这两种策略的快慢,每次选择较快的策略,当起点的人数少于4时直接处理,即可得出结果。

 

三、具体代码  

 1 // greedy algorithm
 2 #include <cstdio>
 3 
 4 int MIN_(int a, int b){
 5     if(a>b) return b;
 6     else return a;
 7 }
 8 
 9 int main(){
10     int t, n, tmp, speed[1005];
11     scanf("%d", &t);
12     while(t--){
13         scanf("%d", &n);
14         for(int i=0; i<n; i++){
15             scanf("%d", &speed[i]);
16         }
17         // bubble sort(0->n:small->large)
18         for(int i=0; i<n; i++){
19             for(int j=i; j<n; j++){
20                 if(speed[i] > speed[j]){
21                     tmp = speed[i];
22                     speed[i] = speed[j];
23                     speed[j] = tmp;
24                 }
25             }
26         }
27         // greedy
28         int start = n, ans = 0;
29         while(start){
30             // start = 1,2,3时直接处理 
31             if(start == 1){
32                 ans  += speed[0];
33                 break; 
34             }
35             else if(start == 2){
36                 ans += speed[1];
37                 break;
38             }
39             else if(start == 3){ // 0,2过河,0回程,0,1过河 
40                 ans += speed[2]+speed[0]+speed[1];
41                 break;
42             }
43             // start>3根据策略选择 
44             else{
45                 ans += MIN_(speed[1]+speed[0]+speed[start-1]+speed[1], speed[start-1]+2*speed[0]+speed[start-2]);
46                 start -= 2; 
47             } 
48         } 
49         printf("%d\n", ans);
50     }
51     
52     return 0;
53 } 
View Code

 

 

 

 

 

posted on 2016-07-13 22:28  快去创造奇迹~  阅读(4547)  评论(0编辑  收藏  举报

导航