倒油问题
有一位厨师要从12斤油(A桶)倒出6斤油但现在手里只有8斤和5斤的桶,怎么取出6斤。
Bucket类
package 搜索.oilTest.common;
public class Bucket {
public int max;//油桶最大容量
public int now;//油桶中的油有多少
public Bucket(int max, int now) {
this.max = max;
this.now = now;
}
public int canIn(){//油桶能倒进多少油
return max-now;
}
public int canOut(){//油桶能倒出多少油
return now;
}
public void in(int a){//倒进a
now+=a;
}
public void out(int a){//倒出b
now-=a;
}
@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;
}
}
DumpCase类
package 搜索.oilTest.common;
import java.util.Arrays;
public class DumpCase {
public Bucket[] buckets = null;
public DumpCase parents = null;
public DumpCase(Bucket[] buckets) {
this.buckets = buckets;
}
public DumpCase(DumpCase u){
buckets=new Bucket[u.buckets.length];
for(int i=0;i<buckets.length;i++){
buckets[i]=new Bucket(0,0);
buckets[i].max=u.buckets[i].max;
buckets[i].now=u.buckets[i].now;
}
}
@Override
public String toString() {
return "A=" +buckets[0].now+ " B="+buckets[1].now+ " C="+buckets[2].now;
}
@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;
}
}
MySet自定义集合类
package 搜索.oilTest.common;
public class MySet {
Object[] objs=new Object[0];//不能用static 不然数据会串扰
public boolean add(Object obj){
if(contain(obj)){
return false;
}
Object[] temp=new Object[objs.length+1];
System.arraycopy(objs, 0, temp, 0, objs.length);
temp[objs.length]=obj;
objs=temp;
return true;
}
public boolean contain(Object obj) {
for(Object o:objs){
if(o.equals(obj)){
return true;
}
}
return false;
}
public Object[] getAll(){
return objs;
}
public int size(){
return objs.length;
}
}
深搜倒油
package 搜索.oilTest.dfs;
import 搜索.oilTest.common.Bucket;
import 搜索.oilTest.common.DumpCase;
import 搜索.oilTest.common.MySet;
public class DumpOilDfs1 {
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);
}
private static void dfs(DumpCase u, MySet caseSet) {
// 鸿沟
if (u.buckets[0].now == 6 || u.buckets[1].now == 6) {
// System.out.println(u);
print(u, caseSet);
return;
}
// 把油桶i中的油倒向j
// DumpCase temp=u;不能这样做 ,会发生捆绑
DumpCase temp = new DumpCase(u);
for (int i = 0; i < temp.buckets.length; i++) {
for (int j = 0; j < temp.buckets.length; j++) {
if (i == j) {
continue;
}
// 判断能倒多少油
int icanDump = temp.buckets[i].canOut();
if (icanDump > temp.buckets[j].canIn()) {
icanDump = temp.buckets[j].canIn();
}
// 倒油
temp.buckets[i].out(icanDump);
temp.buckets[j].in(icanDump);
if (caseSet.contain(temp)) {
temp.buckets[j].out(icanDump);
temp.buckets[i].in(icanDump);
continue;
}
DumpCase v = new DumpCase(temp);
v.parents = u;
caseSet.add(v);
dfs(v, caseSet);
// 还原现场
temp.buckets[i].in(icanDump);
temp.buckets[j].out(icanDump);
temp.parents = null;// 可以省略
}
}
}
private static void print(DumpCase u, MySet caseSet) {
MySet set = new MySet();
set.add(u);
DumpCase d = u.parents;
while(d!=null){
set.add(d);
d = d.parents;
}
System.out.println("--------------");
Object objs[] = set.getAll();
for(Object obj: objs){
System.out.println(obj);
}
}
}
广搜倒油
package 搜索.oilTest.bfs;
import csx.myset.v1.MySet;
import 搜索.oilTest.common.Bucket;
import 搜索.oilTest.common.DumpCase;
public class DumpOilbfs {
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);
CaseQue que = new CaseQue();
que.enque(u);
bfs(que, caseSet);
}
private static void bfs(CaseQue que, MySet caseSet) {
while (!que.isEmpty()) {
DumpCase u = que.deque();
// 满足条件 输出结果
if (u.buckets[0].now == 6 || u.buckets[1].now == 6) {
print(u, caseSet);
continue;
}
DumpCase temp = new DumpCase(u);
for (int i = 0; i < temp.buckets.length; i++) {
for (int j = 0; j < temp.buckets.length; j++) {
// 不能自己向自己倒油
if (i == j) {
continue;
}
// 要倒多少油
int iCanDump = temp.buckets[i].canOut();
if (iCanDump > temp.buckets[j].canIn()) {
iCanDump = temp.buckets[j].canIn();
}
// 等于0不用倒
if (iCanDump == 0) {
continue;
}
// 倒油
temp.buckets[i].out(iCanDump);
temp.buckets[j].in(iCanDump);
// 判断是否已经存在
if (caseSet.contains(temp)) {
temp.buckets[j].out(iCanDump);
temp.buckets[i].in(iCanDump);
continue;
}
// 到这里,说明这种倒法是可以的,而且之前没出现过,可以从此结点搜索下去
// 对这种情况进行记录,注意要拷贝一份新的存入集体,否则会和下一次循环发现捆绑
DumpCase v = new DumpCase(temp);
v.parents = u;
caseSet.add(v); // 记录到已经搜索的结点集合当中
que.enque(v);// 加入到广搜队列当中
// 必须还原,以便从该结点继续尝试其它路径
temp.buckets[j].out(iCanDump);
temp.buckets[i].in(iCanDump);
}
}
}
}
private static void print(DumpCase u, MySet caseSet) {
MySet set = new MySet();
set.add(u);
DumpCase d = u.parents;
while (d != null) {
set.add(d);
d = d.parents;
}
System.out.println("-----------");
Object objs[] = set.getAll();
for (int i = objs.length - 1; i >= 0; i--) {
System.out.println(objs[i]);
}
}
}
class CaseQue {
DumpCase[] que = new DumpCase[100];
int end = 0;
public int enque(DumpCase u) {
que[end++] = u;
return end;
}
public DumpCase deque() {
if (isEmpty()) {
return null;
}
DumpCase u = que[0];
if (end > 1) {
for (int i = 0; i < end; i++) {
que[i] = que[i + 1];
}
}
end--;
return u;
}
public boolean isEmpty() {
if (end == 0) {
return true;
} else {
return false;
}
}
}