过河问题
时间限制:1000 ms | 内存限制:65535KB
难度:5
- 描述
在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。
- 输入
- 第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0 - 输出
- 输出所有人都过河需要用的最少时间
- 样例输入
141 2 5 10
- 样例输出
17
- 来源
- POJ
- 上传者
- 张云聪
简化模型到最后 每次应该是2个人过去 一个人回来 所以每次河对岸应该是最后增加一个人
然后对于每次过河回来的人应该是河对岸的过河速度最快的人
很自然的想到 每次都把最快的人带去 那么让最快的人回来 那么回来的时间最短
但是当n=4的时候 我们可以发现 可能出现问题,就是 我们让最快和次快的人先过河 然后让最快的回来,之后再让2个最慢的人过去,次快的人回来,2个最快的人过去,这样 满足 timer[0]+timer[2]>2*timer[1]的时候之前的结论推翻了,现在我们就该认识的这种情况下我们应该分情况讨论
接下来我们要确认是否还有特殊情况,先思考当有n个人过河, 那么timer[n-1] 这个过河时间 肯定是省不了的,那么我们就应该考虑让船的返回时间最短,现在考虑 n>4的情况, 这样按照上一段的讨论,最慢和次慢的人应该一起分析,最后获取到的时间分别对应着将最慢和次慢的人送到对岸的时间,时间不可缩短,所以最后就可以得出下列程序
import java.util.Arrays;
import java.util.Scanner;
//acm_47
public class PassRiver {
publicstatic void main(String[] args) {
PassRiver passRiver = new PassRiver();
passRiver.solution();
}
public voidsolution() {
in = newScanner(System.in);
int groups =in.nextInt();
for (int i =0; i < groups; i++) {
getDate();
System.out.println(handle(num));
}
}
Scannerin;
intnum;
int[] timer;
private voidgetDate(){
num =in.nextInt();
timer = newint[num];
for(int i =0 ; i < timer.length;i++){
timer[i] =in.nextInt();
}
Arrays.sort(timer);
}
//这里的逻辑是对数据进行处理,准备采用递归的方法,穿进去的是剩余的人数
private inthandle(int index){
switch(index){
case 1:
return timer[0];
case 2:
return timer[1];
case 3:
returntimer[0]+timer[1]+timer[2];
}
return Math.min(timer[0]+timer[index-2],2*timer[1])+timer[index-1]+timer[0] + handle(index-2);
}
}