1.题目
在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,四人所需要的时间分别是1、2、5、8分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这四人尽快过桥。
2.算法
构造N个人(N≥1)过桥最佳方案的方法:
设A、B为走得最快和次快的旅行者,过桥所需时间分别为a、b;而Z、Y为走得最慢和次慢的旅行者,过桥所需时间分别为z、y。
1) 如果N=2,AB一起过桥。
t=b
2) 如果N=3,ABC三人,A+C过,A回;A+B过。t=a+b+c
3) 如果N≥4,那么有两种过河模式,将ZY送到对岸,人数-2:模式一:A+Z过,A回;A+Y过,A回
t1=2*a+y+z
模式二:A+B过,A回;Z+Y过,B回
t2=a+2*b+z
比较两种模式:
t1-t2=a+y-2b
当2b>a+y时,t1<t2,使用模式一;
否则,使用模式二。
这样下来每次人数-2,直到人数<4时结束递归,得到过河消耗的时间。
3.代码
import java.util.Arrays;
import java.util.Scanner;
/**
* @author Administrator
*/
public class River {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
System.out.println("请输入过河人数:");
int n=sc.nextInt();
int[] a=new int[n];
System.out.println("请输入过河人员情况:");
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
}
Arrays.sort(a);
System.out.println(getMinTime(a,n));
}
/**
* 递归,n人过河时间=(n-2)人过河时间+送走时间最长的两个人消耗时间
* @param a 过河人员情况
* @param n 每次递归的人即为a的前n位(n每次递归-2,当n<4时,递归结束)
* @return 返回每个阶段的时间,直到结束
*/
public static int getMinTime(int[] a,int n){
if(n==3){
return a[0]+a[1]+a[2];
}
else if(n==2){
return a[1];
}
//判断两个模式应该选择哪一种
int t1=2*a[0]+a[n-2]+a[n-1];
int t2=a[0]+2*a[1]+a[n-1];
int t;
if((a[0]+a[n-2])<(2*a[1])){
t=t1;
}
else{
t=t2;
}
return getMinTime(a,n-2)+t;
}
}
4.结果