野人与传教士问题实验报告

来源:互联网 发布:xmind 破解版 linux 编辑:程序博客网 时间:2024/06/06 22:44

问题介绍:

在河的左岸有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,intp){}    //构造方法

        public intgetJoeNum(){}               //获取传教士人数

        public intgetWildNum(){}     //获取野人人数

        public intgetPosition(){}                 //获取船的位置

        public boolean isSame(Statuss){}                 //判断两个状态是否完全一致

        public boolean isSafe(Processprocess){}    //经过传入的过程后,是否能使左岸、右岸处于安全状态

}

 

Public class Process {

        private int position =0;         //船的位置

        private int joeNum =0;          //传教士数目

        private int wildNum = 0;         //野人数目

        public Process(int p,int j,int w){} //构造方法

        public intgetPosition(){}                 //获取船的位置

        public intgetJoeNum(){}               //获取传教士数目

        public intgetWildNum(){}     //获取野人数目

}

 

public class Merge {

        private Status status;

        private Process process;

-----------------------------------------------

        public Merge(Status status,Processprocess){}  //构造方法

        public StatusgetStatus(){}   //获得该节点中的状态

        public void setStatus(Status status){} //设置该节点的状态

        public ProcessgetProcess(){}                //获得该节点的操作

        public void setProcess(Processprocess){}  //设置该节点的操纵

}

 

public class Project {

        private ArrayList> mergeList = new ArrayList>();//用于存储所有找到的可行路径,从其中找到最优路径

        private ArrayList merge = newArrayList();    //用于遍历过程中存放遍历路径

        private ArrayList best = newArrayList();        //存放最优路径

        private ArrayList statusList = newArrayList();       //存放所有状态 

        private ArrayListprocessList = new ArrayList();//存放所有过程

        public static int joe = 0,wild = 0,content = 0,max = 10000,num =1;   //基本信息初始化

        private StatusoriStatus,aimStatus;     //原始状态和目标状态对象

---------------------------------------------------------------------------------------------------------------------------------

        public static void main(String args[]){}//主函数,程序入口

        public Project(Stringargs[]){}                //构造方法,参数为运行时附带输入的参数

        public void getBaseData(Stringargs[]){}             //获得基本的数据,将字符转化为int型,并实例化初始状态,目标状态对象

        public voidsetProcessList()         //产生所有可能的操作

                  for(int i = 0;i <= joe;i ++){

                           for(int j = 0;j <= wild;j ++){

                                    for(int k = 0;k < 2;k ++){

                                              if(content>=i+j&&i+j!= 0&&(i>=j||i ==0)){

                                                       processList.add(new Process(k,i,j));

                                                       //System.out.println(i +"  "+j +"   "+ k);

                                              }

                                    }

                           }

                  }

                  System.out.println("");

        }

        public boolean check(Statussta){}                //检测传入的状态是否已经遍历过了

        public void print(ArrayListmer){} //打印结果

public void copy(ArrayListbest,ArrayListmerge){}      //将已经找到的结果拷贝给best放入结果链表中

public voidLooking(){

                  Status status;

                  while(!merge.isEmpty()){                 //如果Merge不为空,则说明没有完全遍历

                           status =merge.get(merge.size()-1).getStatus();  //获得要遍历的状态

                                  if(status.isSame(aimStatus)){         //如果是目标状态

                                    ArrayList mer = newArrayList();      //将遍历过程放入mer

                                    copy(mer,merge);

                                   mergeList.add(mer);       //将所有可能的结果放入结果集

                                    merge.remove(merge.size()-1);     //此状态出栈

                                    return;

                           }

                           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);       //用于保存经过这个操作后变成的状态

                                    status.getWildNum()-processList.get(i).getWildNum(),1);

                                              if(check(sta)){           //检测这个状态是否已经经历过

                                                               merge.add(newMerge(sta,processList.get(i)));   //加入遍历队列

                                                       Looking(); //进行下一层遍历

                                              }

                                    }

                                    if(status.isSafe(processList.get(i))&&status.getPosition()== 1){ //当前状态不是目标状态

                                              Status sta = newStatus(status.getJoeNum()+processList.get(i).getJoeNum(),status.getWildNum()+processList.get(i).getWildNum(),0);//检测经过该操作后是否还是安全状态,且该状态是左岸

 

                                                                status.getWildNum()+processList.get(i).getWildNum(),0);

                                                      if(check(sta)){        //检测这个状态是否已经经历过

                                                       merge.add(new Merge(sta,processList.get(i))); //加入遍历队列

                                                       Looking(); //进行下一层遍历

                                              }

                                    }

                           }

                           merge.remove(merge.size()-1);     //出栈

                           return;

                  }

        }

public voidclear(){}                //系统最后的结果输出

原创粉丝点击