NYOJ 47 過河問題 (貪心)
阿新 • • 發佈:2018-12-24
過河問題
時間限制:1000 ms | 記憶體限制:65535 KB 難度:5- 描述
-
在漆黑的夜裡,N位旅行者來到了一座狹窄而且沒有護欄的橋邊。如果不借助手電筒的話,大家是無論如何也不敢過橋去的。不幸的是,N個人一共只帶了一隻手電筒,而橋窄得只夠讓兩個人同時過。如果各自單獨過橋的話,N人所需要的時間已知;而如果兩人同時過橋,所需要的時間就是走得比較慢的那個人單獨行動時所需的時間。問題是,如何設計一個方案,讓這N人儘快過橋。
- 輸入
- 第一行是一個整數T(1<=T<=20)表示測試資料的組數
每組測試資料的第一行是一個整數N(1<=N<=1000)表示共有N個人要過河
每組測試資料的第二行是N個整數Si,表示此人過河所需要花時間。(0<Si<=100) - 輸出
- 輸出所有人都過河需要用的最少時間
- 樣例輸入
-
1 4 1 2 5 10
- 樣例輸出
-
17
分析:
如果n==1或者n==2,所有人直接過河即可;
如果n==3,用時最短的和用時最長的一起過去,然後用時最短的回來,再和剩下的一個人過去 ;
如果n>=4,設a[0]表示用時最短的人所用的時間,a[1]為用時第二短的人所用的時間,a[n-1]表示用時最長的人所用的時間,a[n-2]表示用時第二長的人所用的時間。那麼:
當2a[1] + a[0] + a[n-1] > 2a[0] + a[n-1] + a[n-2]時,就先讓用時最短的人和用時最長的人一起過去,然後用時最短的回來,接著讓用時最短的和用時第二長的一起過去,再讓用時最短的回來。
否則,就先讓用時最短的和用時第二短的一起過去,然後用時最短的回來,接著讓用時最長和用時第二長的一起過去,再讓用時第二短的回來。這樣就相當於剩下了n-2個人。對這n-2個人執行相同的操作,知道剩下不足4個人即可。
#include<stdio.h> #include<algorithm> using namespace std; int a[1005]; int main() { int T, n, i; scanf("%d",&T); while(T--) { scanf("%d",&n); for(i = 0; i < n; i++) scanf("%d",&a[i]); sort(a,a+n); int sum = 0; while(n >= 4) { if((a[1] * 2 + a[n-1] + a[0]) > (2 * a[0] + a[n-1] + a[n-2])) { //求出最長的兩個人過橋所用的最短時間 sum += a[n-1]; //用時最短的和用時最長的一起過去 sum += a[0]; //用時最短的回來 sum += a[n-2]; //用時最短的和用時第二長的一起過去 sum += a[0]; //用時最短的回來 } else { sum += a[1]; //最短的和第二短的一起過去 sum += a[0]; //最短的回來 sum += a[n-1]; //最長的和第二長的一起過去 sum += a[1]; //第二短的回來 } n -= 2; } if(n == 3) sum += a[1] + a[0] + a[2]; else if(n == 2) sum += a[1]; else sum += a[0]; printf("%d\n",sum); } return 0; }