关于微软面试题:"四人过桥"问题的思考——“n人过桥”问题的演进(Java实现)

来源:互联网 发布:牛仔衬衫 男 知乎 编辑:程序博客网 时间:2024/04/29 17:34

关于微软面试题:"四人过桥"问题的思考——“n人过桥”问题的演进(Java实现) 收藏
前段时间,在CSDN上无意中看到有人发表了一道微软面试题——“4人过桥”问题的算法,只是一直忙于手头上的工作,没有能够在短期实现。当时就是想,如果把这个问题用计算机语言实现的话,有些多此一举,即使我们用穷举法,也只不过是18种情况。所以就没有深入思考,一直没有用Java来实现具体代码。

问题是这样的:

问题:四人夜过桥,步行时间分别为 1、2、5、10 分钟,四人只有一台手电筒,一趟最多两人过桥,一趟过桥须持手电筒,时间以最慢者计,问 17 分钟内可否过桥,如何过桥?

(仅仅针对4人过桥,可以参考http://blog.csdn.net/hikaliv/archive/2009/08/24/4479956.aspx)

今天无意中想起递归算法,突生灵感,如果用Java语言实现“n人过桥”问题,那就有意思了。

递归的出口是:“2人过桥”情况。2人过桥,不需要有人返回,所以非常简单,总时间就是单人所需时间中的最大值。

如果是“n人过桥”(n>=3),那完全可以递归了。

假设是从桥头A至桥头B,桥头A的人群为一个集合,桥头B的人群为另一个集合。

那么首先可以从A中任意选择2个人从A到B;则A集合中减少2个人,B集合中增加2个人;

然后需要一个人从B返回A,这个可以分析出如果想要比较少的时间,一定是从B中选一个单独需时最短的;此时B中减少一个人,A集合中增加一个人;

之后情况变成了“n-1人过桥”问题。

递归思想就开始起作用了。

但是需要注意一点,我在这里的思想是每次返回的人都是从B集合中选出需时最少的;如果想找出需时最多的,就从B中选出一个需时最大的;如果想找到所有情况,那就需要遍历B集合,那就比较复杂了,我没有考虑。

如下是我的代码,由于时间仓促,没有规范化处理。。。比如passMethod中的参数列表中第三个参数其实是可以去掉的,因为它就是桥头A端得人数,可以从第一个参数中获得。

由于时间有限,我在这里就不改动了。

读者可以自己个界面,允许人/机交互,如果深入思考,还是很有意思的。

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
package dfy.bridge;  
 
import java.util.Vector;  
 
public class BridgePass {  
      
    private Vector v_source = null;  
    private Vector v_destination = null;  
    private static int time_total = 0;  
      
    public BridgePass()  
    {  
        v_source = new Vector();  
        v_destination = new Vector();  
    }  
      
    public void setSource(int[] array, int num){  
        for(int i=0; i<num; i++){  
            v_source.addElement(array[i]);  
        }  
    }  
      
    public Vector getSource(){  
        return v_source;  
    }  
      
    public Vector getDestination(){  
        return v_destination;  
    }  
      
    /** 
     * the recursive algorithm. 
     * @param src : the set of persons in A-side 
     * @param des : the set of persons in B-side 
     * @param size : the number of persons in A-side 
     * @param totalTime : the totalTime has used 
     */ 
    public void passMethod(Vector src, Vector des, int size, int totalTime)  
    {  
          
        //If only 2 persons in A-side, just pass bridge together in one time.  
        if(size == 2){  
            System.out.println("A->B:"+src.elementAt(0)+" AND "+ src.elementAt(1));  
            System.out.println("*****Total Time: "+(totalTime + Math.max((Integer)src.elementAt(0),(Integer)src.elementAt(1)))+"****");  
        } else if(size >= 3){  
              
            // if more than 2 persons in A-Side, use the recursive algorithm.  
            for(int i=0; i<size; i++){  
                for(int j=i+1; j<size; j++){  
                    System.out.println("i="+i+"j="+j);  
                    //Pass, A->B  
                      
                    Vector _src = new Vector();  
                    Vector _des = new Vector();  
                    _src = (Vector)src.clone();  
                    _des = (Vector)des.clone();  
                      
                    int time1 = 0;  
                    int time2 = 0;  
                                          
                    time1 = (Integer)_src.elementAt(i);  
                    _des.addElement(time1);  
                      
                    time2 = (Integer)_src.elementAt(j);  
                    _des.addElement(time2);  
                      
                    System.out.print("A->B:"+ time1);  
                    System.out.println(" AND "+ time2);  
                      
                    _src.removeElement(time1);  
                    _src.removeElement(time2);  
                      
                    //BACK, B->A  
                      
                    int minValue = (Integer)_des.elementAt(0);  
                    for(int k=0 ; k<_des.size(); k++){  
                        if(((Integer)_des.elementAt(k)).intValue() < minValue){  
                            minValue = (Integer)_des.elementAt(k);  
                        }  
                    }  
                      
                    _src.addElement(minValue);  
                    _des.removeElement(minValue);  
                      
                    System.out.println("B->A:"+minValue);  
                      
                    passMethod(_src, _des, _src.size(), totalTime + Math.max(time1, time2) + minValue);  
                      
                }  
                  
            }  
        }   
    }  
      
      
    public static void main(String[] cmd)  
    {  
        BridgePass test = new BridgePass();  
          
        //the persons want to pass bridge:  
        int source[] = {1,2,5,10};  
          
        test.setSource(source, source.length);  
        test.passMethod(test.getSource(), test.getDestination(), source.length, 0);  
          
    }  
 
 

package dfy.bridge;

import java.util.Vector;

public class BridgePass {
 
 private Vector v_source = null;
 private Vector v_destination = null;
 private static int time_total = 0;
 
 public BridgePass()
 {
  v_source = new Vector();
  v_destination = new Vector();
 }
 
 public void setSource(int[] array, int num){
  for(int i=0; i<num; i++){
   v_source.addElement(array[i]);
  }
 }
 
 public Vector getSource(){
  return v_source;
 }
 
 public Vector getDestination(){
  return v_destination;
 }
 
 /**
  * the recursive algorithm.
  * @param src : the set of persons in A-side
  * @param des : the set of persons in B-side
  * @param size : the number of persons in A-side
  * @param totalTime : the totalTime has used
  */
 public void passMethod(Vector src, Vector des, int size, int totalTime)
 {
  
  //If only 2 persons in A-side, just pass bridge together in one time.
  if(size == 2){
   System.out.println("A->B:"+src.elementAt(0)+" AND "+ src.elementAt(1));
   System.out.println("*****Total Time: "+(totalTime + Math.max((Integer)src.elementAt(0),(Integer)src.elementAt(1)))+"****");
  } else if(size >= 3){
   
   // if more than 2 persons in A-Side, use the recursive algorithm.
   for(int i=0; i<size; i++){
    for(int j=i+1; j<size; j++){
     System.out.println("i="+i+"j="+j);
     //Pass, A->B
     
     Vector _src = new Vector();
     Vector _des = new Vector();
     _src = (Vector)src.clone();
     _des = (Vector)des.clone();
     
     int time1 = 0;
     int time2 = 0;
          
     time1 = (Integer)_src.elementAt(i);
     _des.addElement(time1);
     
     time2 = (Integer)_src.elementAt(j);
     _des.addElement(time2);
     
     System.out.print("A->B:"+ time1);
     System.out.println(" AND "+ time2);
     
     _src.removeElement(time1);
     _src.removeElement(time2);
     
     //BACK, B->A
     
     int minValue = (Integer)_des.elementAt(0);
     for(int k=0 ; k<_des.size(); k++){
      if(((Integer)_des.elementAt(k)).intValue() < minValue){
       minValue = (Integer)_des.elementAt(k);
      }
     }
     
     _src.addElement(minValue);
     _des.removeElement(minValue);
     
     System.out.println("B->A:"+minValue);
     
     passMethod(_src, _des, _src.size(), totalTime + Math.max(time1, time2) + minValue);
     
    }
    
   }
  }
 }
 
 
 public static void main(String[] cmd)
 {
  BridgePass test = new BridgePass();
  
  //the persons want to pass bridge:
  int source[] = {1,2,5,10};
  
  test.setSource(source, source.length);
  test.passMethod(test.getSource(), test.getDestination(), source.length, 0);
  
 }


}
 

在测试代码中(main方法中),我们可以自己随意设置source参数,这里我还是沿用了“4人过桥”原参数。

控制台输出结果为:

A->B:1 AND 2
B->A:1
A->B:5 AND 10
B->A:2
A->B:1 AND 2
*****Total Time: 17****
A->B:5 AND 1
B->A:1
A->B:10 AND 1
*****Total Time: 19****
A->B:10 AND 1
B->A:1
A->B:5 AND 1
*****Total Time: 19****
A->B:1 AND 5
B->A:1
A->B:2 AND 10
B->A:2
A->B:1 AND 2
*****Total Time: 20****
A->B:2 AND 1
B->A:1
A->B:10 AND 1
*****Total Time: 19****
A->B:10 AND 1
B->A:1
A->B:2 AND 1
*****Total Time: 19****
A->B:1 AND 10
B->A:1
A->B:2 AND 5
B->A:2
A->B:1 AND 2
*****Total Time: 20****
A->B:2 AND 1
B->A:1
A->B:5 AND 1
*****Total Time: 19****
A->B:5 AND 1
B->A:1
A->B:2 AND 1
*****Total Time: 19****
A->B:2 AND 5
B->A:2
A->B:1 AND 10
B->A:1
A->B:2 AND 1
*****Total Time: 20****
A->B:1 AND 2
B->A:1
A->B:10 AND 1
*****Total Time: 20****
A->B:10 AND 2
B->A:2
A->B:1 AND 2
*****Total Time: 21****
A->B:2 AND 10
B->A:2
A->B:1 AND 5
B->A:1
A->B:2 AND 1
*****Total Time: 20****
A->B:1 AND 2
B->A:1
A->B:5 AND 1
*****Total Time: 20****
A->B:5 AND 2
B->A:2
A->B:1 AND 2
*****Total Time: 21****
A->B:5 AND 10
B->A:5
A->B:1 AND 2
B->A:1
A->B:5 AND 1
*****Total Time: 23****
A->B:1 AND 5
B->A:1
A->B:2 AND 1
*****Total Time: 23****
A->B:2 AND 5
B->A:2
A->B:1 AND 2
*****Total Time: 24****

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fengyud/archive/2009/10/09/4647139.aspx

原创粉丝点击