我的天!!!!!!!!!!!!!!!!!!!!!!!
我终于把这该死的三个水桶把水分成两半了!!!!!!!!!!!!
今天我用下午和晚上的时间研究用三个水桶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; } }
下面是作者的博客,跟书上差不多,大家参考。
http://blog.csdn.net/orbit/article/details/6596521
十二点半了,我该下了。明天有课