状态树搜索算法-------------抽象问题与建模思想(三只水桶分水问题)

我的天!!!!!!!!!!!!!!!!!!!!!!!

我终于把这该死的三个水桶把水分成两半了!!!!!!!!!!!!

今天我用下午和晚上的时间研究用三个水桶8L,5L,3L把8L水分成两份(4L)

晚上我从八点种时间开始写算法,写了4个小时,除了其中半个小时的洗澡,我一直在想,该如何实现。。。。。。

其中被那个备忘录卡了我一个半小时!!!!!!!!(谢天谢地,我终于把它搞出来了,现在我欣喜的心情无以复加!!!!!!!!!!)

好了,情感发泄完了,该步入正题了,总结我今天的算法学习。

今天看《算法的乐趣》第五章,作者提出问题:把三桶个水桶等分8升水的问题,有8,5,3L的水桶分8升水,最后的结果要在8L水桶和5L水桶中分别有4L水。

首先要定义问题的解,并分析解空间范围和拓扑结构,然后根据解空间的范围和拓扑结构设计遍历搜索算法。



建立数学模型,根节点为初始状态,叶子节点可能是最终状态,也可能是某个无法转换的最终中间状态,有多少个最终状态叶子节点就要多少种答案。


现在是12点17分,室友在聊天,可能会打错几个字,大家不要介意。


状态的数学模型与状态树:状态的数学模型可以用一个一维数组存放,状态树就是建立起节点与节点之间的联系。

倒水动作的数学模型:合法的倒水动作包含3个要素:倒出水的桶、接收水的桶、倒水的体积。{from,to,water}


搜索算法:确定状态树模型后,第二个重要的问题是:状态树的搜索算法。

可用深度优先也可以广度优先,我写的是深度优先。

状态树的搜索就是对整个树进行遍历,其中还暗含了状态的生产。


状态树的剪枝和重复状态的判断

为了避免状态树的重复和环形死循环,一定要有备忘录。

我就是在处理备忘录的时候没有理解作者的思想,所以出了bug。

后来我用往前遍历,终于成功解决了,得出了16个答案,但是时间原因,我就不写输出过程的算法了。

下面是我的实现代码:

主类,创建状态树对象,传入一个根节点

package 状态数搜索算法;

public class Main {
	public static void main(String[] args) {
		Main ma = new Main();
		ma.initMain();
	}
	public void initMain(){
		DumpWater dw = new DumpWater();
		int[] str = {8,0,0};
		StateNode state = new StateNode(str);
		dw.SearchState(state);
	}
}

递归倒水算法:

package 状态数搜索算法;

import java.util.Vector;

public class DumpWater {
	public int count = 0;
	public void SearchState(StateNode state){//检查每一个状态是否是最终状态,不是的话就继续检索
		if(state.IsFinalState()){//判断节点是否为最终状态
			count++;
			System.out.println(count+":"+"Succeed!");
			return ;
		}
		for(int j=0;j<state.bucket.length;j++){
			for(int i=0;i<state.bucket.length;i++){
				SearchStateAction(state, i, j);
			}
		}
	}
	public void SearchStateAction(StateNode state,int from,int to){
		if(state.CanTakeDumpAction(from, to)){//判断当前状态能否倒水
			StateNode next = new StateNode(state.bucket);
			next.back = state;
			boolean bDump = state.Dump_Wate(from, to, next);
			if( bDump && !Tool.IsProcessedState(next) ){
				SearchState(next);
			}
		}
	}
	
}

状态树节点:

package 状态数搜索算法;

public class StateNode {//水桶节点
	public int[] bucket = new int[3];//水桶
	public StateNode back;
	public int getMax(int bucket){
		if( bucket == 0 ){
			return 8;
		}else if( bucket == 1 ){
			return 5;
		}else if( bucket == 2 ){
			return 3;
		}
		return 0;
	}
	public StateNode(int[] str){
		this.bucket[0] = str[0];
		this.bucket[1] = str[1];
		this.bucket[2] = str[2];
	}
	public boolean Dump_Wate(int from,int to,StateNode next){
		int dump_Water = next.getMax(to) - next.bucket[to];
//		System.out.println(from+"倒去"+to+"  dump_Water-- >"+dump_Water);
		if( next.bucket[from] >= dump_Water ){
			next.bucket[to] = next.bucket[to] + dump_Water;
			next.bucket[from] = next.bucket[from] - dump_Water;
		}else{
			next.bucket[to] = next.bucket[to] + next.bucket[from];
			dump_Water = next.bucket[from];
			next.bucket[from] = 0;
		}
		if( dump_Water > 0 ){
			next.SetAction(dump_Water, from, to,next);
			return true;
		}
		return false;
	}
	
	public boolean IsFinalState(){
		if( bucket[0] == 4 && bucket[1] == 4 && bucket[2] == 0){//判断是否为最终状态
			return true;
		}else{
			return false;
		}
	}
	/**
	 * 判断水桶编号是否在012
	 * from 和 to 不相同
	 * from没满,to不为空
	 * @param from
	 * @param to
	 * @return
	 */
	public boolean CanTakeDumpAction(int from,int to){
		if( from>=0 && from<3 && to>=0 && to<3 ){//判断水桶编号是否在0、1、2中
			if( (from != to) && 
					IsBucketEmpty(from)
					&& IsBucketFull(to)){//倒水水桶不是自己,倒水水桶没空,被倒水桶不满,可以倒
				return true;
			}
		}
		return false;
	}
	/**
	 * 判断水桶是否为空
	 * 有水就返回true
	 * 空就返回false
	 * @param from
	 * @return
	 */
	public boolean IsBucketEmpty(int from){//判断倒水的桶是否为空
		if(bucket[from] > 0){//如果水桶有水,返回true
			return true;
		}else{
			return false;//空返回false
		}
	}
	/**
	 * 判断水桶是否已经装满
	 * 如果满了,返回false
	 * 如果可以装就返回true
	 */
	public boolean IsBucketFull(int to){//判断被倒水的水桶是否已满
		if(to == 0 && bucket[to]<8 && bucket[to]>=0 ){//如果水桶是一号,水量大于0且小于8,没满,返回true
			return true;
		}else if(to == 1 && bucket[to]<5 && bucket[to]>=0 ){//2号水桶,水量大于0小于8,没满,返回true
			return true;
		}else if(to == 2 && bucket[to]<3 && bucket[to]>=0 ){//3号水桶,水量大于0小于3,没满,返回true
			return true;
		}
		return false;
	}
	/**
	 * ???
	 * @param dump_Water
	 * @param from
	 * @param to
	 * @param next
	 */
	public void SetAction(int dump_Water,int from,int to,StateNode next){
		
	}
	public String getText(StateNode state){
		String s1 = Integer.toString(state.bucket[0]);
		String s2 = Integer.toString(state.bucket[1]);
		String s3 = Integer.toString(state.bucket[2]);
		String s = s1 + s2 + s3;
		return s;
	}
}
工具类:

package 状态数搜索算法;

import java.util.HashMap;
import java.util.Vector;

public class Tool {
	public static Vector<String> vector = new Vector<String>();
	public static boolean IsProcessedState(StateNode state){
		StateNode current = state ;
		while( state.back != null ){//逐一对比当前状态跟上面状态
			if(current.getText(current).contains(state.back.getText(state.back))){
				return true;
			}
			state = state.back;
		}
		
		return false;
	}
	
}

状态树搜索算法-------------抽象问题与建模思想(三只水桶分水问题)_第1张图片
这个算法作者用C++做的,我用java实现。

下面是作者的博客,跟书上差不多,大家参考。

http://blog.csdn.net/orbit/article/details/6596521

十二点半了,我该下了。明天有课

你可能感兴趣的:(算法,搜索)