过河问题

来源:互联网 发布:ubuntu出错 编辑:程序博客网 时间:2024/05/20 13:37

过河问题

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
描述

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

输入
第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)
输出
输出所有人都过河需要用的最少时间
样例输入
141 2 5 10
样例输出

17


思路:假设N个旅行者的过桥时间分别为(已排序){T1, T2, T3, T4 ... Tn},N个旅行者过桥的最快时间为sum。 从简单入手,如果N = 1, sum = T1;如果N = 2,  sum = max(T1, T2);如果N = 3, sum = T1+T2+T3。如果N > 3,考虑最慢和次慢两个人的过桥方法。共有两种方案。
     第一种,最快和次快的人先过去(用时T[1]),然后最快的人回来(用时T[0]),接着最慢和次慢的人过去(用时T[n-1]),最后次快的人回来(用时T[1])。整理后为T[0] + T[1] + T[1] + T[n-1]。
     第二种,最快和最慢的过去(用时T[n-1]),然后最快的回来(用时T[0]),接着最快和次慢的人过去(用时T[n-2]),最后最快的人回来(用时T[0])。整理后为T[0] + T[0] + T[n-1] + T[n-2]。
     选用时少的方案,这样旅行者的数量减少了两个,递归求解即可。


//非递归实现
#include<iostream>
#include<algorithm>
using namespace std;


int sum=0;
int CrossRivorProblem(int *T,int n)
{
 if(n==1) return T[0];
 if(n==2) return T[1];
 if(n==3) return T[0]+T[1]+T[2];
while(1){
if(n==2) {sum+=T[1];break;}
if(n==3) {sum+=T[2];break;}
int t1 = T[0]+T[1]+T[1]+T[n-1];   //方案1  
         int t2 = T[0]+T[0]+T[n-1]+T[n-2]; //方案2  
         sum+= (t1>t2?t2:t1);  
         n-=2;  
}
 return sum;
}




int main(){
int i; 
int T[1000];
int n;
cin>>n;
for(i=0;i<n;i++)
cin>>T[i];
sort(T,T+n);
CrossRivorProblem(T,n);
cout<<sum<<endl;
return 0;


}










//递归实现
/*#include<iostream>
#include<algorithm>
using namespace std;


int CrossRivorProblem(int *T,int n)
{
 if(n==1) return T[0];
 else if(n==2) return T[1];
 else if(n==3) return T[0]+T[1]+T[2];
 else  
    {  
        int t1 = T[0] + T[1] + T[1] + T[n-1];   //方案1  
        int t2 = T[0] + T[0] + T[n-1] + T[n-2]; //方案2  
        int t = t1 > t2 ? t2 : t1;  
  
        return CrossRiver(T, n - 2) + t;  
    }  
}
*/

0 0