zoukankan      html  css  js  c++  java
  • 狼和羊过河问题

    package guohe;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * 狼羊过河问题
     * @author tiger
     * @date 2011年1月27日。
     * 
     * 这里是用面向对象的编程方式,有定义了狼和羊两个类。
     * 但其实程序里并没有用到它们的行为,该问题只是关心它们的数目而已!
     * 所以其实可以直接就定义四个变量来存储两岸的狼数和羊数,然后在遍历
     * 递归的同时增减这四个数字即可。
     * 
     */
    public class Guohe {
    
    	//左岸的狼数和羊数
    	private List<Actor> leftLangs = new LinkedList<Actor>();
    	private List<Actor> leftYangs = new LinkedList<Actor>();
    	
    	//右岸的狼数和羊数
    	private List<Actor> rightLangs = new LinkedList<Actor>();
    	private List<Actor> rightYangs = new LinkedList<Actor>();
    	
    	//存储所有成功过河的方案
    	private List winSteps = new ArrayList();
    	
    	public Guohe() {
    		init();
    	}
    	
    	/**
    	 * 刷新重置盘面为初始情况
    	 */
    	private void init() {
    		leftLangs.clear();
    		leftYangs.clear();
    		rightLangs.clear();
    		rightYangs.clear();
    		for (int i = 0; i < 3; i++) {
    			leftLangs.add(new Lang());
    			leftYangs.add(new Yang());
    		}
    		
    		//这两个状态需要初始放进去。
    		states.add("3,3,0,0,1");
    		states.add("3,3,0,0,2");
    		
    		//方向设为初始向对岸的方向
    		fangxiang = TYPE_FANGXIANG_GO;
    	}
    	
    	
    	//到对岸:go , 回来:come 
    	private static int TYPE_FANGXIANG_GO = 1;
    	private static int TYPE_FANGXIANG_COME = 2;
    	//船行方向
    	private int fangxiang = TYPE_FANGXIANG_GO;
    	
    	/**
    	 * 保存盘面的状态
    	 * 
    	 * 保存的是有5个数字的字符串,这5个数字代表的意义依次是:
    	 * 左岸狼数、左岸羊数、右岸狼数、右岸羊数、当前船行方向。
    	 * 
    	 * 状态的保存非常重要,把所有递归遍历遇到的状态都保存在这里,
    	 * 当后面的某次遍历所遇到的盘面已经有在states里存在的话,说明该
    	 * 盘面已经被处理过,则可以直接跳过。
    	 * 
    	 * 保存下已经处理过的盘面,这样的设计可以防止出现死循环导致内存泄露。
    	 */
    	private List states = new ArrayList();
    	
    	
    	/**
    	 * 针对当前船行方向,根据当前盘面情况,即两岸的狼数和羊数
    	 * 得到可以上船的狼数和羊数。 该方法中会把盘面状态保存入states.
    	 * @param fangxiang
    	 * @return
    	 */
    	private List<int[]> getChuanMember(int fangxiang)
    	{
    		List<int[]> rtnlist = new LinkedList<int[]>();
    		String key = "";
    		
    		List alangs, ayangs, blangs, byangs;
    		if(fangxiang == TYPE_FANGXIANG_GO)
    		{
    			alangs = leftLangs;
    			ayangs = leftYangs;
    			blangs = rightLangs;
    			byangs = rightYangs;
    		}else{
    			alangs = rightLangs;
    			ayangs = rightYangs;
    			blangs = leftLangs;
    			byangs = leftYangs;
    		}
    		
    		//判断 1,0 .(1狼0羊)
    		if(alangs.size() >= 1)
    		{
    			if((alangs.size() - 1 <= ayangs.size() || ayangs.size() == 0) && (blangs.size() + 1 <= byangs.size() || byangs.size() == 0))
    			{
    				if(fangxiang == TYPE_FANGXIANG_GO)
    				{
    					key = (alangs.size() - 1) + "," + ayangs.size() + "," + (blangs.size() + 1) + "," + byangs.size() + "," + TYPE_FANGXIANG_GO;
    				}else{
    					key = (blangs.size() + 1) + "," + byangs.size() + "," + (alangs.size() - 1) + "," + ayangs.size() + "," + TYPE_FANGXIANG_COME;
    				}
    				
    				if(!states.contains(key))
    				{
    					rtnlist.add(new int[]{1, 0});
    					states.add(key);
    				}
    			}
    		}
    		
    		//判断 2,0 .(2狼0羊)
    		if(alangs.size() >= 2)
    		{
    			if((alangs.size() - 2 <= ayangs.size() || ayangs.size() == 0) && (blangs.size() + 2 <= byangs.size() || byangs.size() == 0))
    			{
    				if(fangxiang == TYPE_FANGXIANG_GO)
    				{
    					key = (alangs.size() - 2) + "," + ayangs.size() + "," + (blangs.size() + 2) + "," + byangs.size() + "," + TYPE_FANGXIANG_GO;
    				}else{
    					key = (blangs.size() + 2) + "," + byangs.size() + "," + (alangs.size() - 2) + "," + ayangs.size() + "," + TYPE_FANGXIANG_COME;
    				}
    				
    				if(!states.contains(key))
    				{
    					rtnlist.add(new int[]{2, 0});
    					states.add(key);
    				}
    			}
    		}
    		
    		//判断0,1 .(0狼1羊)
    		if(ayangs.size() >= 1)
    		{
    			if((alangs.size() <= ayangs.size() - 1 || ayangs.size() - 1 == 0) && (blangs.size() <= byangs.size() + 1 || byangs.size() + 1 == 0))
    			{
    				if(fangxiang == TYPE_FANGXIANG_GO)
    				{
    					key = alangs.size() + "," + (ayangs.size() - 1) + "," + blangs.size() + "," + (byangs.size() + 1) + "," + TYPE_FANGXIANG_GO;
    				}else{
    					key = blangs.size() + "," + (byangs.size() + 1) + "," + alangs.size() + "," + (ayangs.size() - 1) + "," + TYPE_FANGXIANG_COME;
    				}
    				
    				if(!states.contains(key))
    				{
    					rtnlist.add(new int[]{0, 1});
    					states.add(key);
    				}
    			}
    		}
    		//判断0,2 .(0狼2羊)
    		if(ayangs.size() >= 2)
    		{
    			if((alangs.size() <= ayangs.size() - 2 || ayangs.size() - 2 == 0) && (blangs.size() <= byangs.size() + 2 || byangs.size() + 2 == 0))
    			{
    				if(fangxiang == TYPE_FANGXIANG_GO)
    				{
    					key = alangs.size() + "," + (ayangs.size() - 2) + "," + blangs.size() + "," + (byangs.size() + 2) + "," + TYPE_FANGXIANG_GO;
    				}else{
    					key = blangs.size() + "," + (byangs.size() + 2) + "," + alangs.size() + "," + (ayangs.size() - 2) + "," + TYPE_FANGXIANG_COME;
    				}
    				
    				if(!states.contains(key))
    				{
    					rtnlist.add(new int[]{0, 2});
    					states.add(key);
    				}
    			}
    		}
    		
    		//判断1,1 .(1狼1羊)
    		if(alangs.size() >= 1 && ayangs.size() >= 1)
    		{
    			if((alangs.size() - 1 <= ayangs.size() - 1 || ayangs.size() - 1 == 0) && (blangs.size() + 1 <= byangs.size() + 1 || byangs.size() + 1 == 0))
    			{
    				if(fangxiang == TYPE_FANGXIANG_GO)
    				{
    					key = (alangs.size() - 1) + "," + (ayangs.size() - 1) + "," + (blangs.size() + 1) + "," + (byangs.size() + 1) + "," + TYPE_FANGXIANG_GO;
    				}else{
    					key = (blangs.size() + 1) + "," + (byangs.size() + 1) + "," + (alangs.size() - 1) + "," + (ayangs.size() - 1) + "," + TYPE_FANGXIANG_COME;
    				}
    				
    				if(!states.contains(key))
    				{
    					rtnlist.add(new int[]{1, 1});
    					states.add(key);
    				}
    			}
    		}
    		return rtnlist;
    	}
    	
    	/**
    	 * 用来存储当前遍历的方案步骤
    	 * 
    	 * 存储的是大小为3的数字数组。各元素的意义依次是:
    	 * 船行方向、船上狼数、船上羊数
    	 * 
    	 */
    	private List<int[]> temp = new ArrayList<int[]>();
    	
    	/**
    	 * 递归方法,不断深度遍历
    	 */
    	private void digui()
    	{
    		//得到当前盘面下,可以上船的狼数和羊数
    		List list = this.getChuanMember(fangxiang);
    		
    		//如果找不到可乘船的狼羊,则说明当前的盘面无法走向成功,则退出。
    		if(list.isEmpty())
    		{
    			//重置为初始盘面情况
    			init(); 
    			//清空之前的步骤存储
    			temp.clear();
    			return;
    		}
    		for (int i = 0; i < list.size(); i++) {
    			int[] element = (int[]) list.get(i);
    			
    			if(fangxiang == TYPE_FANGXIANG_GO)
    			{				
    				//修改两岸的狼数
    				if(element[0] == 1)
    				{					
    					Actor a = this.leftLangs.remove(0);
    					this.rightLangs.add(a);
    				}
    				else if(element[0] == 2)
    				{
    					Actor a = this.leftLangs.remove(0);
    					this.rightLangs.add(a);
    					a = this.leftLangs.remove(0);
    					this.rightLangs.add(a);
    				}
    				//修改两岸的羊数
    				if(element[1] == 1)
    				{					
    					Actor a = this.leftYangs.remove(0);
    					this.rightYangs.add(a);
    				}
    				else if(element[1] == 2)
    				{
    					Actor a = this.leftYangs.remove(0);
    					this.rightYangs.add(a);
    					a = this.leftYangs.remove(0);
    					this.rightYangs.add(a);
    				}
    				
    				//存储步骤
    				temp.add(new int[]{fangxiang, element[0], element[1]});
    				//判断是否完成,如果完成,将完成步骤加入完成方案的列表里
    				if(this.success())
    				{
    					//打印成功方案
    					System.out.println("方案:(共" + temp.size() + "步)");
    					for (int j = 0; j < temp.size(); j++) {
    						int[] a = (int[]) temp.get(j);
    						System.out.println("第" + (j + 1) + "步, " + (a[0] == 1 ? "前进" : "后退") + "---> 狼" + a[1] + ",羊" + a[2]);
    					}
    					winSteps.add(temp);
    					
    					//重置盘面为初始情况
    					init();
    					//清空之前的步骤存储
    					temp.clear();
    					return; //这里是return而非continue,是因为既然已经成功了,而当前是最后一步,那么后面的循环必然不能成功。--->不大肯定。
    				}
    				fangxiang = TYPE_FANGXIANG_COME;
    				digui();
    			}
    			else if(fangxiang == TYPE_FANGXIANG_COME)
    			{				
    				//修改两岸的狼数
    				if(element[0] == 1)
    				{					
    					Actor a = this.rightLangs.remove(0);
    					this.leftLangs.add(a);
    				}
    				else if(element[0] == 2)
    				{
    					Actor a = this.rightLangs.remove(0);
    					this.leftLangs.add(a);
    					a = this.rightLangs.remove(0);
    					this.leftLangs.add(a);
    				}
    				//修改两岸的羊数
    				if(element[1] == 1)
    				{					
    					Actor a = this.rightYangs.remove(0);
    					this.leftYangs.add(a);
    				}
    				else if(element[1] == 2){
    					Actor a = this.rightYangs.remove(0);
    					this.leftYangs.add(a);
    					a = this.rightYangs.remove(0);
    					this.leftYangs.add(a);
    				}
    				//存储步骤
    				temp.add(new int[]{fangxiang, element[0], element[1]});
    				//调换方向
    				fangxiang = TYPE_FANGXIANG_GO;
    				//递归处理现在的盘面
    				digui();
    			}
    		}
    	}
    	
    	
    	private boolean success()
    	{
    		return this.leftLangs.isEmpty() && this.leftYangs.isEmpty() && this.rightLangs.size() == 3 && this.rightYangs.size() == 3;
    	}
    	
    	
    	
    	public static final int TYPE_LANG = 1;
    	public static final int TYPE_YANG = 2;
    	class Actor {
    		public int type = 0;
    		public boolean isLang()
    		{
    			return type == TYPE_LANG;
    		}
    		public boolean isYang()
    		{
    			return type == TYPE_YANG;
    		}
    	}
    	//狼
    	class Lang extends Actor{
    		public Lang() {
    			type = TYPE_LANG;
    		}
    	}
    	//羊
    	class Yang extends Actor{
    		public Yang() {
    			type = TYPE_YANG;
    		}
    	}
    	
    	public static void main(String[] args) {
    		new Guohe().digui();
    	}
    	
    }
    
    
  • 相关阅读:
    【转】ORACLE Dataguard安装
    win7 配置微软的深度学习caffe
    深度学习-开源方案
    Python之包管理工具
    C#调用Python脚本的简单示例
    转Python 和C#的交互
    转-使用 CefSharp 在 C# App 中嵌入 Chrome 浏览器
    转-在Mac OS上搭建Python的开发环境
    Weex入门与进阶指南
    A couple of notes about .NET Framework 4.6 setup behaviors
  • 原文地址:https://www.cnblogs.com/chaohi/p/1947136.html
Copyright © 2011-2022 走看看