问题介绍:

在河的左岸有N个传教士、N个野人和一条船,传教士们想用这条船把所有人都运过河去,但有以下条件限制:

(1)修道士和野人都会划船,但船每次最多只能运K个人;

(2)在任何岸边以及船上,野人数目都不能超过修道士,否则修道士会被野人吃掉。

假定野人会服从任何一种过河安排,请规划出一个确保修道士安全过河的计划。

问题分析:

因为船的承载能力有限,所以船上载人过河的方案有限,首先把所有的过河时合理的过河过程,此外,因为要考虑左岸和右岸都要符合要求,所以要明确两岸的位置状态,为了使整个问题简单化,我们以左岸情况为关注点,运算过程中只要保证右岸符合条件即可。在左岸状态下,搜索在当前状态下,经过合法的过程后,依然使左岸、右岸保持合法的状态。我这里采用递归的深度遍历思想,在找到目标状态后,回溯到当前函数的上一层,继续推算其他的情况,直到所有情况完全遍历,结束搜索。在深度遍历的过程中,使用栈Merge来存储需要遍历的状态节点,同时把所有此状态经过合法过程到达的合法状态放入栈Merge中,进行递归,递归函数最后将此层递归的状态出栈。当搜索到目标状态后,把整个状态栈存放到一个存放遍历路径的数组MergeList中,即为一条遍历路径。当搜索结束后,可以通过MergeList数组找出所有的最优路径。

需要的实体类有:


public class Status {
       private int joeNum = 0;  //传教士数量
       private int wildNum = 0;         //野人数量
       private int position = 0; //船所在的位置,0位于左岸,1位于右岸
-----------------------------------------------
       public Status(int j,int w,int p){}     //构造方法
       public int getJoeNum(){}                 //获取传教士人数
       public int getWildNum(){}      //获取野人人数
       public int getPosition(){}                  //获取船的位置
       public boolean isSame(Status s){}                  //判断两个状态是否完全一致
       public boolean isSafe(Process process){}     //经过传入的过程后,是否能使左岸、右岸处于安全状态
}

Public class Process {
       private int position = 0;          //船的位置
       private int joeNum = 0;           //传教士数目
 
 
        private int wildNum = 0;           //野人数目
 
 
       public Process(int p,int j,int w){}  //构造方法
       public int getPosition(){}                  //获取船的位置
       public int getJoeNum(){}                 //获取传教士数目
       public int getWildNum(){}      //获取野人数目
}

public class Merge {
       private Status status;
       private Process process;
-----------------------------------------------
       public Merge(Status status,Process process){}   //构造方法
       public Status getStatus(){}    //获得该节点中的状态
       public void setStatus(Status status){} //设置该节点的状态
       public Process getProcess(){}                  //获得该节点的操作
       public void setProcess(Process process){}   //设置该节点的操纵
}

public class Project {
       private ArrayList> mergeList = new ArrayList>(); //用于存储所有找到的可行路径,从其中找到最优路径
       private ArrayList merge = new ArrayList();     //用于遍历过程中存放遍历路径
       private ArrayList best = new ArrayList();         //存放最优路径
       private ArrayList statusList = new ArrayList();        //存放所有状态 
       private ArrayListprocessList = new ArrayList(); //存放所有过程
       public static int joe = 0,wild = 0,content = 0,max = 10000,num = 1;   //基本信息初始化
       private Status oriStatus,aimStatus;      //原始状态和目标状态对象
---------------------------------------------------------------------------------------------------------------------------------
       public static void main(String args[]){} //主函数,程序入口
       public Project(String args[]){}                 //构造方法,参数为运行时附带输入的参数
       public void getBaseData(String args[]){}               //获得基本的数据,将字符转化为int型,并实例化初始状态,目标状态对象
       public void setProcessList(){           //产生所有可能的操作
                 
                          
                                   
                                             
                                                      
                                                       //System.out.println(i +"  "+j + "  
                                             
                                   
                          
                 
                 
       
       public boolean check(Status sta){}                 //检测传入的状态是否已经遍历过了
       public void print(ArrayListmer){}  //打印结果
public void copy(ArrayListbest,ArrayList merge){}       //将已经找到的结果拷贝给best放入结果链表中
public void Looking(){
                 
                  while(!merge.isEmpty()){                  //如果Merge不为空,则说明没有完全遍历
                           status = merge.get(merge.size()-1).getStatus();   //获得要遍历的状态
                                    if(status.isSame(aimStatus)) {          //如果是目标状态
                                    ArrayList mer = new ArrayList();       //将遍历过程放入mer中
                                   
                                    mergeList.add(mer);        //将所有可能的结果放入结果集
                                     merge.remove(merge.size()-1);      //此状态出栈
                                   
                          
                           for(int i = 0;i < processList.size();i ++){    //当前状态不是目标状态
                                    if(status.isSafe(processList.get(i))&&status.getPosition() == 0){  //检测经过该操作后是否还是安全状态,且该状态是左岸
                                              Status sta = newStatus(status.getJoeNum()-processList.get(i).getJoeNum(),status.getWildNum()-processList.get(i).getWildNum(),1);        //用于保存经过这个操作后变成的状态
                                   
                                              if(check(sta)){            //检测这个状态是否已经经历过
                                                                merge.add(new Merge(sta,processList.get(i)));    //加入遍历队列
                                                       Looking(); //进行下一层遍历
                                             
                                   
                                    if(status.isSafe(processList.get(i))&&status.getPosition() == 1){ //当前状态不是目标状态
                                              Status sta = new Status(status.getJoeNum()+processList.get(i).getJoeNum(),status.getWildNum()+processList.get(i).getWildNum(),0);//检测经过该操作后是否还是安全状态,且该状态是左岸

                                                               
                                                       if(check(sta)){          //检测这个状态是否已经经历过
                                                       merge.add(new Merge(sta,processList.get(i))); //加入遍历队列
                                                       Looking(); //进行下一层遍历
                                             
                                   
                          
                           merge.remove(merge.size()-1);      //出栈
                          
                 
       
public void clear(){}                  //系统最后的结果输出