深度搜索倒油:
样题描述:有a、b、c三个油桶;a桶的容量为12斤,现有12斤油;b桶容量为8斤,现有0斤;c桶容量5斤,现有0斤。现一次只能由一个桶向另一个同倒油,问怎样才能倒出6斤油。
package cn.hncu.search.oil.dfs; import cn.hncu.search.oil.common.Bucket; import cn.hncu.search.oil.common.DumpCase; import cn.hncu.search.oil.common.Myset; public class DumpOilDFS { public static void main(String[] args) { Bucket buckets[] = new Bucket[3]; buckets[0] = new Bucket(12, 12); buckets[1] = new Bucket(8, 0); buckets[2] = new Bucket(5, 0); DumpCase u = new DumpCase(buckets); Myset caseSet = new Myset(); caseSet.add(u); dfs(u,caseSet); } public static void print(DumpCase u,Myset caseSet){ Myset set = new Myset(); set.add(u); DumpCase d = u.getParent(); while(d!=null){ set.add(d); d = d.getParent(); } System.out.println("------------"); Object objs[] = set.getAll(); for(int i=objs.length-1; i>=0; i--){ DumpCase v = (DumpCase) objs[i]; System.out.println(v.getBuckets()[0].now+","+v.getBuckets()[1].now+","+v.getBuckets()[2].now); } } public static void dfs(DumpCase u0, Myset caseSet){ //递归鸿沟 for(Bucket bucket: u0.getBuckets()){ if(bucket.now==6){ //System.out.println("find a case"); print(u0,caseSet); return; } } int n = u0.getBuckets().length;//桶的个数 DumpCase u = new DumpCase(u0); //用备份节点去搜 //遍历所有的DumpCase: 依次让桶i向j倒 for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ //自己不能给自己倒 if(i==j){ continue; } //算出桶i给j倒时,能倒多少-->canDump int canDump = u.getBuckets()[i].canOut(); if(u.getBuckets()[i].canOut()>u.getBuckets()[j].canIn()){ canDump = u.getBuckets()[j].canIn(); } //倒油 u.getBuckets()[i].out(canDump); u.getBuckets()[j].in(canDump); //System.out.println(u.getBuckets()[0].now+","+u.getBuckets()[1].now+","+u.getBuckets()[2].now); //判断该情况是否已经出现过了//如果存在,要还原(把油倒回去) if(caseSet.contains(u)){ //把油还回去 u.getBuckets()[i].in(canDump); u.getBuckets()[j].out(canDump); continue; } //经过上面的哨兵,说明这样倒可以 DumpCase v = new DumpCase(u); v.setParent(u0); caseSet.add(v); //System.out.println(v.getBuckets()[0].now+","+v.getBuckets()[1].now+","+v.getBuckets()[2].now); dfs(v,caseSet); //再倒回去,以重新进行下一个邻居的遍历 u.getBuckets()[i].in(canDump); u.getBuckets()[j].out(canDump); } } } }
package cn.hncu.search.oil.common; public class Bucket { public int max; public int now; public Bucket(int max, int now) { this.max = max; this.now = now; } public void in(int a){ now += a; } public void out(int a){ now -=a; } public int canIn(){ return max-now; } public int canOut(){ return now; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + max; result = prime * result + now; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Bucket other = (Bucket) obj; if (max != other.max) return false; if (now != other.now) return false; return true; } }
package cn.hncu.search.oil.common; import java.util.Arrays; public class DumpCase { Bucket buckets[]; DumpCase parent = null; public DumpCase() { } public DumpCase(Bucket buckets[]) { this.buckets = buckets; } //必须要进行深拷贝 public DumpCase(DumpCase u) { this.buckets = new Bucket[ u.getBuckets().length ]; for(int i=0; i<u.getBuckets().length;i++){ buckets[i] = new Bucket(0,0); buckets[i].max = u.getBuckets()[i].max; buckets[i].now = u.getBuckets()[i].now; } } public Bucket[] getBuckets() { return buckets; } public DumpCase getParent() { return parent; } public void setParent(DumpCase parent) { this.parent = parent; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(buckets); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DumpCase other = (DumpCase) obj; if (!Arrays.equals(buckets, other.buckets)) return false; return true; } //※1 用“特征串”来代表整个对象,如果特征串相等,则表示是相等的对象。这样在比较对象时,性能就提高了 public String toString(){ return "A="+buckets[0].now+",B="+buckets[1].now+",C="+buckets[2].now; } }
package cn.hncu.search.oil.common; public class Myset { private Object[] objs= new Object[0]; public boolean contains(Object obj){ for(Object tmp: objs){ if(tmp.equals(obj)){ return true; } } return false; } public boolean add(Object obj){ if(contains(obj)){ return false; } Object[] tempObjs = new Object[objs.length+1]; System.arraycopy(objs, 0, tempObjs, 0, objs.length); tempObjs[objs.length] = obj; objs = tempObjs; return true; } public Object[] getAll(){ return objs; } public int size(){ return objs.length; } }