过河问题
时间限制: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
- 来源
- POJ
-
解题思路:
首先按照过河时间从小到大排序,当n>3时候,就是考虑用最小时间先把用时最长的两个人送过河,
且手电筒仍然留在未过河的这边,剩下的再依次求解。把当前用时最长的两个人送过河可以考虑两种方案:
方案一:
1 号和 2 号先过河,然后 1 号回来,n 号和 n-1 号过河,然后 2 号再回来
用时:2*a[2]+a[1]+a[n];
方案二:
1 号和 n 号先过河,然后 1 号再回来,1 号和 n-1 号再过河,之后 1 号再回来
用时:a[n]+a[n-1]+2*a[1];
所以每次把用时最长的两个人送过河用时应该取上述两种方案中的最小值。至于为什么要先考虑
把用时最长的两个人送个和用的是贪心的思想,因为只有两个用时最长的两个人一块过河才能保证
用时次长的人不会占用过河时间,将时间降到最低(我是这样考虑的,不知道对不对。。)代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 5 using namespace std; 6 7 int a[1005]; 8 9 int min(int a, int b) 10 { 11 return a < b ? a : b; 12 } 13 14 int fun(int n) 15 { 16 if(n <= 2) 17 return a[n]; 18 else if(n == 3) 19 return a[1]+a[2]+a[3]; 20 else 21 { 22 return fun(n-2) + min(a[n]+a[n-1]+2*a[1], a[n]+a[1]+2*a[2]); 23 } 24 } 25 26 int main() 27 { 28 int T, n; 29 scanf("%d", &T); 30 while(T--) 31 { 32 scanf("%d", &n); 33 for(int i = 1; i <= n; ++i) 34 scanf("%d", &a[i]); 35 sort(a+1, a+n+1); 36 printf("%d\n", fun(n)); 37 } 38 return 0; 39 }