搜索---BFS---倒油

71 篇文章 0 订阅
35 篇文章 0 订阅

    BFS是什么就不多少了

直接来个题目---倒油:

    有一位厨师要从盛12斤油(a桶)的桶中倒出6斤油来,可是手边只有盛8斤油(b桶)和盛5斤油(c桶)的两个桶,问如何操作才能将6斤取出来呢?

题解:   

     采用面向对象去做,面向对象最主要的是要注意引用直接的捆绑,这个是采用面向对象解题的一大坑,很练手,可以加大对引用和基本数据类型的认识。具体过程如下(有3个类):

主类:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

/**
 * Time:2018/3/29
 * Description:进行解决倒油问题的主类
 * @author 宋进宇
 */
public class PourOil {

	public static void main(String[] args) {
		Buckets buckets=init();//初始化化根节点
		//广搜必备的队列
		Queue<Buckets> que = new LinkedList<Buckets>();
		que.add(buckets);
		//用来记录树所有节点
		ArrayList<Buckets> list = new ArrayList<Buckets>();
		list.add(buckets);
		bfs(que,list);
	}
	/**
	 * 广搜 --- 找出最短倒出6斤油的路径
	 * @param que 进行广搜的辅助队列
	 * @param list 存放每个节点的情况
	 */
	private static void bfs(Queue<Buckets> que, ArrayList<Buckets> list) {
		//取出队首
		Buckets buckets = que.poll();
		if (buckets==null) {
			return ;
		}
		//只要有一个油桶的油量为6斤就打印路径
		for (int i = 0; i < buckets.getOilBuckets().length; i++) {
			if (buckets.getOilBuckets()[i].getExist()==6) {
				print(buckets);
				return;
			}
		}
		//备份节点
		Buckets temp = new Buckets(buckets);
		//buckets 的子节点
		//油桶i给油桶j倒油
		for (int i = 0; i < temp.getOilBuckets().length; i++) {
			for (int j = 0; j < temp.getOilBuckets().length; j++) {
				if (i==j) {//自己给自己倒油没意义
					continue;
				}
				//i给j倒油
				int add = temp.getOilBuckets()[j].add(temp.getOilBuckets()[i]);
				if (add==0) {//如果倒出空就与  buckets 情况相同,即跳过
					continue;
				}
				//倒出油的情况
				Buckets newBuckets = new Buckets(temp);
				//如果先前没有出现过这种情况,则是该树节点加人队列
				if (!list.contains(newBuckets)) {
					newBuckets.setParent(buckets);
					list.add(newBuckets);
					que.add(newBuckets);
				}
				//把油倒回去,继续找  buckets 的子节点
				temp.getOilBuckets()[j].pourOut(temp.getOilBuckets()[i],add);
			}
		}
		bfs(que, list);
	}
	/**
	 * 打印一条路径
	 * @param buckets 该路径的叶子节点  也就是 最底层的节点
	 */
	private static void print(Buckets buckets) {
		if (buckets==null) {
			return ;
		}
		Buckets parent = buckets.getParent();
		StringBuilder sb = new StringBuilder(buckets.toString());
		while(parent!=null){
			sb.insert(0, parent.toString());
			parent = parent.getParent();
		}
		System.out.println(sb.toString());
	}
	/**
	 * 初始化油桶的集合
	 * @return 油桶的集合
	 */
	private static Buckets init() {
		Buckets buckets = new Buckets();
		OilBucket obs[] =new OilBucket[3];
		obs[0] = new OilBucket(12, 12);
		obs[1] = new OilBucket(8, 0);
		obs[2] = new OilBucket(5, 0);
		buckets.setOilBuckets(obs);
		return buckets;
	}
}

辅助类(树的节点):

/**
 * Time:2018/3/29
 * Description:存放油桶的数组对象
 * @author 宋进宇
 */

public class Buckets {
	
	private OilBucket[] oilBuckets;//用对象数组存放所有油桶
	private Buckets parent; //记录父节点
	
	/**
	 * 空参构造
	 */
	public Buckets() {
	}
	/**
	 * 拷贝对象的构造函数  ---深拷贝(解除引用赋值捆绑)
	 * @param buckets 被拷贝的对象
	 */
	public Buckets(Buckets buckets) {
		if (buckets==null||buckets.oilBuckets.length==0) {
			return; 
		}
		this.oilBuckets = new OilBucket[buckets.oilBuckets.length];
		for (int i = 0; i < buckets.oilBuckets.length; i++) {
			this.oilBuckets[i] = new OilBucket(buckets.oilBuckets[i].getVolume(), buckets.oilBuckets[i].getExist());
		}
	}
	/**
	 * 获取父节点对象
	 * @return 父节点
	 */
	public Buckets getParent() {
		return parent;
	}
	/**
	 * 设置父节点
	 * @param parent 父节点
	 */
	public void setParent(Buckets parent) {
		this.parent = parent;
	}
	/**
	 * 获取油桶的集合
	 * @return 油桶的集合
	 */
	public OilBucket[] getOilBuckets() {
		return oilBuckets;
	}
	/**
	 * 设置油桶的集合
	 * @param oilBuckets 油桶的集合
	 */
	public void setOilBuckets(OilBucket[] oilBuckets) {
		this.oilBuckets = oilBuckets;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Buckets other = (Buckets) obj;
		///以下是根据题目需求来判断是否相等/
		for (int i = 0; i < oilBuckets.length; i++) {
			//只要有一个油桶里面的油量不同 说明两个油桶集合不相同
			if (oilBuckets[i].getExist()!=other.getOilBuckets()[i].getExist()) {
				return false;
			}
		}
		return true;
	}
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		if (oilBuckets==null||oilBuckets.length==0) {
			return null;
		}
		sb.append(oilBuckets[0].getExist());
		for (int i = 1; i < oilBuckets.length; i++) {
			sb.append(","+oilBuckets[i].getExist());
		}
		sb.append("\r\n");
		return sb.toString();
	}
	
}

辅助类(油桶):

/**
 * Time:2018/3/29 
 * Description:油桶---倒油问题所需对象
 * @author 宋进宇
 *
 */
public class OilBucket {
	private int volume;// 油桶的容量
	private int exist;// 油桶里已有的油

	public OilBucket() {
	}
	/**
	 * 构造一个油桶
	 * @param volume 油桶的容量
	 * @param exist 油桶里已有的油
	 */
	public OilBucket(int volume, int exist) {
		super();
		this.volume = volume;
		this.exist = exist;
	}

	/**
	 * 把油桶ob中油倒入当前对象中
	 * 
	 * @param ob 倒出油的对象
	 *            
	 * @return 表示倒入油的数量
	 */
	public int add(OilBucket ob) {
		if (ob == null) {
			return 0;
		}
		int add = 0;
		if (volume>=exist+ob.exist) {
			add=ob.exist;
			exist += ob.exist;
			ob.exist =0;
		}else{
			add = volume-exist;
			ob.exist -= add;
			exist = volume;
		}
		return add;
	}

	/**
	 * 把当前对象中的油倒入ob中
	 * 
	 * @param ob 被倒入油的对象
	 * 
	 * @return 表示倒出油的数量
	 */
	public void pourOut(OilBucket ob,int value) {
		if (ob==null) {
			return ;
		}
		exist -= value;
		ob.exist += value;
	}

	public int getVolume() {
		return volume;
	}

	public void setVolume(int volume) {
		this.volume = volume;
	}

	public int getExist() {
		return exist;
	}

	public void setExist(int exist) {
		this.exist = exist;
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值