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;
}
}