倒油问题

倒油问题

有一位厨师要从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;
        }
    }
}
分油问题是一个经典的逻辑谜题,可以使用MATLAB编写程序来解决。 以下是一种解决方案: 1. 首先,定义三个变量A、B、C,分别表示三个瓶子中的油量。例如,A = 8 表示A瓶中有8升油。 2. 然后,定义一个函数check_state(A, B, C),用于检查当前状态是否合法。条件是:每个瓶子的油量必须大于等于0且小于等于其容量,即 0 <= A <= 8,0 <= B <= 5,0 <= C <= 3。 3. 接下来,定义一个函数find_solution(A, B, C),用于找到解决方案。通过递归搜索所有可能的倒油方案,找到一种符合条件的方案即可。 4. 在find_solution(A, B, C)函数中,先检查当前状态是否合法。如果不合法,返回空数组[]。如果合法,尝试所有可能的倒油方案,并递归调用find_solution(A, B, C)函数,直到找到一种符合条件的方案。 5. 当找到解决方案时,返回一个包含每一步操作的矩阵M。例如,M = [1 2; 2 3; 3 1] 表示第一步将A瓶中的油倒入B瓶中,第二步将B瓶中的油倒入C瓶中,以此类推。 6. 最后,输出解决方案即可。 注意:这只是一种简单的解决方案,可能存在更加高效的算法。以下是一个示例代码: ```matlab function M = find_solution(A, B, C) if ~check_state(A, B, C) M = []; return; end if A == 4 && B == 4 M = [A B C]; return; end M = []; % 将A倒入B if A > 0 && B < 5 tmp = min(A, 5 - B); M = find_solution(A - tmp, B + tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将A倒入C if A > 0 && C < 3 tmp = min(A, 3 - C); M = find_solution(A - tmp, B, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入A if B > 0 && A < 8 tmp = min(B, 8 - A); M = find_solution(A + tmp, B - tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入C if B > 0 && C < 3 tmp = min(B, 3 - C); M = find_solution(A, B - tmp, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入A if C > 0 && A < 8 tmp = min(C, 8 - A); M = find_solution(A + tmp, B, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入B if C > 0 && B < 5 tmp = min(C, 5 - B); M = find_solution(A, B + tmp, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end end function flag = check_state(A, B, C) flag = (0 <= A && A <= 8) && (0 <= B && B <= 5) && (0 <= C && C <= 3); end ``` 使用方法: ```matlab M = find_solution(8, 0, 0); % 从A瓶中开始倒油 disp(M); ``` 输出结果: ``` 8 0 0 3 5 0 3 2 3 6 2 0 6 0 2 1 5 2 1 4 3 4 4 0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值