nyoj 47-过河问题 (贪心)

47-过河问题


内存限制:64MB 时间限制:1000ms Special Judge: No
accepted:2 submit: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

分析:
  1、只要我们能够保证每一步都取到时间最短的结果,那么最后得到的结果一定是耗时最短的
  2、有两种走的方法
    ①、由耗时最短的带耗时最长的
    ②、用耗时最长的带耗时第二长的(当然,我们需要一个耗时最短的两个人去带电灯回来)

核心代码:
  
1 int a = A[n-1] + A[n-2] + A[0] + A[0];
2 int b = A[n-1] + A[1] + A[1] + A[0];
3 int c = min(a, b);

C/C++代码实现(AC):

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <stack>
 7 #include <map>
 8 #include <queue>
 9 #include <set>
10 
11 using namespace std;
12 const int MAXN = 1010;
13 
14 int main()
15 {
16     int t;
17     scanf("%d", &t);
18     while(t --)
19     {
20         int n, A[MAXN];
21         scanf("%d", &n);
22         for(int i = 0; i < n; ++ i)
23             scanf("%d", &A[i]);
24 
25         sort(A, A+n, less<int>());
26         if (n <= 2)
27         {
28             printf("%d\n", A[n-1]);
29             continue;
30         }
31         if (n == 3)
32         {
33             printf("%d\n", A[0] + A[1] + A[2]);
34             continue;
35         }
36         int cnt = A[1];
37         while(n > 3)
38         {
39             int a = A[n-1] + A[n-2] + A[0] + A[0];
40             // 最后两位耗时多的全部让第一号来送
41             int b = A[n-1] + A[1] + A[1] + A[0];
42             // 让最前面两个先走,再让第二个带灯回来,让后两个一起走,最后再让最先过来的第一号带灯回来
43 
44             int c = min (a, b); // 选取耗时最短的策略
45             cnt += c;
46             n -= 2;
47             if (n == 3)
48                 cnt += A[2] + A[0];
49         }
50         printf("%d\n", cnt);
51     }
52     return 0;
53 }
 
  

猜你喜欢

转载自www.cnblogs.com/GetcharZp/p/9099953.html