倒水问题解决思路

这个问题是在之前面试一个公司的时候遇到的,以前没遇到过这种问题,猛然上来有点懵逼。不过几分钟整理思路有了些许解题方案,但临时想的方案漏洞还是有些,思路有了,大方向对了,写代码虽然说就简单了,但大脑混沌状态真的是还不一定写出完美的代码。

题意:

给你两个容器 A  B 问是否能够经过有限的步骤倒水,得到容量为 C 的水

输出最小的步数,同时输出每一步的操作。

如果不能达到目标状态,则输出 impossible

思路:

总状态只有那么多, 反正每一步后都只有 6 种操作明显的 BFS 关键是每一步路径的记录。

其实就是个A星算法

每层的操作就六种可能:

一:用水池中的水装满 A

二:用水池中的水装满 B

三:把 A 中的水全部倒进废水池

四:把 B 中的水全部倒进废水池

五:把 A 中的水倒进 B 【不能溢出】

    那么对应可能会有两种状态:用 k1 表示 A 中的水, k2 表示 B 中的水

    如果 k1+k2 <= B 则   k2 = k1+k2; k1 = 0 【不能够装满容器 B】注意顺序

    否则 k1 = k1+k2-B; k2 = B 【能够装满容器 B】

六:把 B 中的水倒进 A 【不能溢出】

    也有两种情况,分析同上

    如果 k1+k2 <= A 则 k1 = k1+k2; k2 = 0;

    否则 k2 = k1+k2-A; k1 = A

之前也参考了网上几个代码,写的还是有点混沌,但说实话感觉还是我这个更清晰

/**
 *
 * @Author: <fujiansheng.com> 
 * @Description:
 * 1:->a
 * 2:->b
 * 3:a->
 * 4:b->
 * 5:a->b
 * 6:b->a
 * @Date: Created in :2019 
 * @Modified by:
 */
public class CurrStatus {
    public int ka=0,kb=0;
    public int op=0;
    public CurrStatus pre;
}
package com.fjsh.mnp;

import com.fjsh.mnp.models.CurrStatus;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @Author: <fujiansheng.com>
 * @Description:
 * @Date: Created in :2019
 * @Modified by:
 */
public class SelfMain {
    public static void main(String[] args) {
        final CurrStatus head = new CurrStatus();
        List<CurrStatus> currStatusList=new LinkedList<CurrStatus>(){{add(head);}};
        int a = 3, b = 5, c = 4;
        CurrStatus tail = dealPool(currStatusList, a, b, c);
        if (tail == null) {
            System.out.println("impossible");
        } else {
            List<Integer> ops=new ArrayList<Integer>();
            while (tail.op != 0) {
               ops.add(tail.op);
                tail = tail.pre;
            }
            for(int i=ops.size()-1;i>=0;i--){
                if(ops.get(i)==1){
                    System.out.println("倒满a");
                }
                if(ops.get(i)==2){
                    System.out.println("倒满b");
                }
                if(ops.get(i)==3){
                    System.out.println("倒出a");
                }
                if(ops.get(i)==4){
                    System.out.println("倒出b");
                }
                if(ops.get(i)==5){
                    System.out.println("a倒入b");
                }
                if(ops.get(i)==6){
                    System.out.println("b倒入a");
                }
            }
        }
    }

    public static CurrStatus dealPool(List<CurrStatus> currStatusList, int a, int b, int pool) {
        if(a+b<pool){
            return null;
        }
        int max=0;
        while (max<a*b){
            List<CurrStatus> currStatuses = new LinkedList<CurrStatus>();
            for (CurrStatus currStatus : currStatusList) {
                //循环处理六种条件
                for (int i = 1; i <= 6; i++) {
                    CurrStatus item = new CurrStatus();
                    item.op = i;
                    item.pre = currStatus;
                    if (i == 1) {
                        item.ka = a;
                        item.kb = currStatus.kb;
                    } else if (i == 2) {
                        item.kb = b;
                        item.ka = currStatus.ka;
                    } else if (i == 3) {
                        item.ka = 0;
                        item.kb = currStatus.kb;
                    } else if (i == 4) {
                        item.kb = 0;
                        item.ka = currStatus.ka;
                    } else if (i == 5) {
                        if (currStatus.ka + currStatus.kb <= b) {
                            item.ka = 0;
                            item.kb = currStatus.ka + currStatus.kb;
                        } else if (currStatus.ka + currStatus.kb > b) {
                            item.kb = b;
                            item.ka = (currStatus.ka + currStatus.kb) - b;
                        }
                    } else if (i == 6) {
                        if (currStatus.ka + currStatus.kb <= a) {
                            item.kb = 0;
                            item.ka = currStatus.ka + currStatus.kb;
                        } else if (currStatus.ka + currStatus.kb > a) {
                            item.ka = a;
                            item.kb = (currStatus.ka + currStatus.kb) - a;
                        }
                    }
                    if (item.ka == pool || item.kb == pool || item.ka
                            + item.kb == pool) {
                        return item;
                    }
                    currStatuses.add(item);
                }
            }
            max++;
            currStatusList=currStatuses;
        }
        return null;

    }
}

附带上当时参考的url:https://www.bbsmax.com/A/n2d99RL6dD/

搞点积分不容易,有兴趣的下载下:https://download.csdn.net/download/a925907195/11173095

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值