深度搜索倒油:
样题描述:有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;
- }
- }