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 }