深度优先搜索例题------Java倒油

深度搜索倒油:

样题描述:有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;
    }
}


你可能感兴趣的:(java,数据结构,算法,搜索,DFS)