《贪心算法》— NYOJ 47 过河问题 详解思路

                                                                过河问题

时间限制:1000 ms  |  内存限制:65535 KB

难度:5

描述

在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。 

输入

第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0

输出

输出所有人都过河需要用的最少时间

样例输入

1
4
1 2 5 10

样例输出

17
思路:
 

这是一道经典的贪心算法的题目。首先说一下我对这道题的理解:

  n个人要过河,已知每个人的过河时间且过河时必须要使用唯一的手电筒。桥只能允许最多

两个人同时过河。让求所有人都过河后的最短时间。

  我们不难知道:必须同时两个人过河,因为要把手电筒送回来,让为过河的人过河。使用贪

心的思想解决这个问题,首先要对这n个人的过河时间排序并保存在数组S中。这也是大多数贪心

解决问题的共同点。

  根据贪心原则,我们有两个贪心策略:

  策略A: 让最快的两个人去送最慢的两个人。首先S[0]和S[1]过河,S[0]把手电筒送回来,接着

最慢的两个人S[n-1],S[n-2]拿着手电筒过河。然后S[1]把手电筒送回来。注意:次慢的这个人相当

于没有花费时间就过去了(相对于策略B来说),这一点对于理解为什么要比较两种策略的最短时间

很重要。 此时S[0],S[1]都在未过河的这一岸,然后S[0],S[1]在接着送目前最慢的两个人S[n-3],

S[n-4],以此类推。

  策略B:一直让最快的人送当前状态最慢的人。S[0]先把S[n-1],送到对岸,拿着手电筒回来,

再送S[n-2]。相当于单独一个人依次过河,再加上最快人的送手电筒的时间。

 

[cpp] view plain copy

  1. #include  
  2. #include  
  3. using namespace std;  
  4. int a[1010];  
  5. int main()  
  6. {  
  7.     int T;  
  8.     scanf("%d",&T);  
  9.     while(T--)  
  10.     {  
  11.         int N,i,sum=0;  
  12.         scanf("%d",&N);  
  13.         for(i=0;i
  14.         scanf("%d",&a[i]);  
  15.         sort(a,a+N);  
  16.         while(N>3){//以四个人为一个单位选出局部最优解,局部的最优得出全局的最优   
  17.             if((a[1]+a[0]+a[N-1]+a[1]+a[1])<(a[1]+a[0]+a[N-1]+a[0]+a[N-2]))  
  18.             sum+=a[1]+a[0]+a[N-1]+a[1];  
  19.             else sum+=a[N-1]+a[0]+a[N-2]+a[0];  
  20.             N=N-2;  
  21.         }  
  22.         if(N==1)  
  23.         sum+=a[0];  
  24.         else if(N==2)  
  25.         sum+=a[1];  
  26.         else if(N==3)  
  27.         sum+=a[1]+a[0]+a[2];  
  28.         printf("%d\n",sum);  
  29.     }  
  30.     return 0;  
  31. }  

你可能感兴趣的:(贪心算法)