本文参考http://blog.csdn.net/kaiwii/article/details/8019538
看完这篇文章中的4人过河问题,第一反应就是拿最小时间的人把所有的人都送到对面,但是算完感觉不怎么对,而且看到作者直接
这样来进行分配,虽然最终的结果的却是比我的算的小,明白自己的答案是错误的,但是不怎么理清楚这时间的节约在哪个地方,看了一会,明白这个的巧妙在于C和D的耗费时间都比较大,所以可以选择将C和D一起过去,节约C的时间,但是又有一个问题,如果对面只有C和D的话,势必C必须要回来,这个则完全没有达到将C的时间节约掉的效果,所以首先将B送过去,在对面则可以让B回来,这个就可以直接将C的时间节约掉了,这个就是这个思路的巧妙之处。
于是作者得出这个结论
所以就进行了分情况讨论
下面附上java翻译的算法
package com.cqut.accrossriver;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/*
* 过桥问题
在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。
不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,
四人所需要的时间分别是1,2,5,8分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。
问题是,你如何设计一个方案,让用的时间最少。
*/
public class AccrossRiver {
public static void main(String[] args){
Scanner inputScanner=new Scanner(System.in);
System.out.print("请输入每人最短时间:");
String timesString=inputScanner.nextLine();
double[] times=stringToArray(timesString);
System.out.println("最小时间为:"+getMinestTime(times));
}
public static double[] stringToArray(String timesString){
if(timesString!=null&&!"".equals(timesString)){
String[] strs=timesString.split(" ");
double[] timeDouble=new double[strs.length];
int i=0;
for(;i<strs.length;i++){
timeDouble[i]=Double.parseDouble(strs[i]);
}
return timeDouble;
}
else{
return null;
}
}
public static double getMinestTime(double[] times){
int size=times.length;
double sum=0.0;
int i=0;
if(size>=4){
/*
* 从最大的两个开始和最小的两个分别分两种情况进行比较
*/
for(i=size-1;i>2;i=i-2){
double resultTimeOne=times[0]+times[1]+times[1]+times[i];
double resultTimeTwo=times[0]+times[0]+times[i-1]+times[i];
if(resultTimeOne<=resultTimeTwo){
System.out.println("0把1送到对岸!,耗时 "+times[0]);
System.out.println("0回到此岸!,耗时 "+times[0]);
System.out.println("1把"+i+"送到对岸!,耗时 "+times[i]);
System.out.println("1回到此岸!,耗时 "+times[1]);
sum+=resultTimeOne;
}
else{
System.out.println("0把"+i+"送到对岸!,耗时 "+times[i]);
System.out.println("0回到此岸!,耗时 "+times[0]);
System.out.println("0把"+(i-1)+"送到对岸!,耗时 "+times[i-1]);
System.out.println("0回到此岸!,耗时 "+times[0]);
sum+=resultTimeTwo;
}
}
}
if(i==2){
System.out.println("2把1送到对岸!,耗时 "+times[2]);
System.out.println("0到达对岸!,耗时 "+times[0]);
sum=sum+times[0]+times[2];
}
else if(i==1){
System.out.println("0把1送到对岸!,耗时 "+times[1]);
sum=sum+times[1];
}
else if(i==0){
System.out.println("0到达对岸!,耗时 "+times[0]);
sum=sum+times[0];
}
return sum;
}
}
这个算法为什么可以能计算多余4个人的情况呢,表面上我们并没有进行四个人以上的讨论,但是其实多个人的计算和四个人的类似,可以说四个人的计算是多个人的最小计算单位,因为我们每次只是考虑最大 第二大 最小 第二小的计算,而多个人的计算只是四个人的重复计算。