过河问题
时间限制: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个人的过河时间已经从小到大排好序用数列 a1 ,a2 ,a3 ,a4 ,... , an ;
当(n =1) time= a[n] ;
当(n >=2) 时:假如n=4时;
(1)
a3 ,a4 怎么过,
肯定是a1 , a2 先过去再a1回来。
然后第一种方法(a)a1和a3 一起过,再a1回来和a4一起过 。
总时间 time1 = a1 + a3 + a1 + a4 ;
第二种方法(b)a3和a4一起过再a2回来和a1一起过。
总时间 time2 =a1 + a4 + a2 + a2 ;
time = min(time1 , time2);取最短的方法;
实质上就是这个判断句if(2*a[2] < a[1]+a[i-1])
例如第一步 a1,a2,先过,时间a2,a1回来,时间a1
第二步,a3,a4,过,时间a4,a2,回来,时间a2, 或者 a1,a4,先过,时间a4,然后,a1回来,时间a1
第三步,a2,a1,过,时间a2, 或者 a1,a3,过,时间a3,,
第一种 a2+a1+a4+a2+a2 第二种 a2+a4+a1+a1+a3
比较两种差别在a2+a2 a1+a3(a3其实就是i-1) 所以解决了这个,问题就解决了,当然当为三个人时,方法固定,先一和三,然后一回去,再加上二就行了;具体代码如下:1 #include<stdio.h> 2 #define MAX 1000 3 int main() 4 { 5 int n_sample, n_person, a[MAX], total_time, i, j, t; 6 scanf("%d",&n_sample); //样例数量 7 while(n_sample--) 8 { 9 scanf("%d",&n_person); //输入人数 10 for(i = 1; i <= n_person; ++i) 11 scanf("%d",&a[i]); //输入每个人的过河时间,空格分开,开始下标用1 12 total_time = 0; 13 14 if(n_person != 1)//选择法进行排序 15 { 16 for(i = 1; i <= n_person - 1; i++) 17 for(j = i+1; j <= n_person; ++j) 18 if(a[j] < a[i]) 19 {t = a[j];a[j] = a[i];a[i] = t;} 20 21 for(i = n_person; i >= 3;) 22 { 23 if(i == 3) //如果是3个人 24 { 25 total_time += a[3]+a[1]; 26 break; 27 } 28 if( 2*a[2] < a[1]+a[i-1]) 29 { 30 total_time += a[1] + 2*a[2] + a[i]; 31 i-= 2; 32 } 33 else 34 { 35 total_time += a[i] + a[1]; 36 i--; 37 } 38 } 39 total_time += a[2]; 40 } 41 else 42 total_time = a[1]; //如果只有一个人 43 printf("%d ",total_time); 44 } 45 return 0; 46 }