人工智能 DFS 水壶问题 Java


一、问题描述

给定两个水壶,一个可以装4升水,一个能装3升水,水壶上没有任何度量标记。有一水龙头可以用来往壶中灌水。问题是怎样在能装4升的水壶里面恰好只装2升水。

二、解决方法

1.定义状态空间

用(x,y)两个有序整数表示状态空间的一个状态,
x表示4L水壶中的水量,x∈[0,4],
y表示3L水壶中的水量,y∈[0,3]。
初始状态为(0,0),目标状态为(2,0)

2.确定一组操作

①x倒满(x=4)
②y倒满(y=3)
③x倒空(x=0)
④y倒空(y=0)
⑤y倒入x(y->x)
⑥x倒入y(x->y)

3.搜索过程

不是很复杂,我就不画流程图了
整体的思路为深度优先搜索,主要通过栈和递归来实现
首先对状态空间进行初始化,设置第一个节点的状态为已访问,并放入栈中
然后通过递归进行深度优先搜索
对每个节点进行六种操作,接着查重,将符合要求的子节点入栈,不断循环,直到x=2,找到目标状态,此时栈中存放的就是一条解决方案,然后我们将其输出
之后重复这个步骤,直到遍历完所有的路径,递归结束

三、代码实现

1.关键代码

首先我用了一个内部类来记录水壶的状态

//声明一个内部类用来记录水壶的状态
    class WaterState {
        int x4;
        int y3;
        int step;//记录进行的是哪一步操作
		//构造器
        WaterState(int x4, int y3, int step) {
            this.x4 = x4;
            this.y3 = y3;
            this.step = step;
        }
    }

深度优先遍历

//深度优先遍历
    void dfs(int x4, int y3) {
        if (x4 == 2) {
            Output(pos);
            pos++;
        }
        else {
            for (int i = 1; i <= 6; i++) {//依次进行六种操作
                WaterState waterState = operate(x4, y3, i);//返回操作后水壶的状态
                if (checkRepeat(waterState.x4, waterState.y3) == 0) {//查重
                    pathStack.add(waterState);//入栈
                    space[waterState.x4][waterState.y3] = 1;//设置为已访问
                    dfs(waterState.x4, waterState.y3);//递归
                    pathStack.pop();//出栈
                    space[waterState.x4][waterState.y3] = 0;//状态重置
                }
            }
        }
    }

2.全部代码

import java.util.Stack;

public class MyPot {

    int[][] space = new int[5][4];//用一个二维数组来记录水壶是否被访问
    Stack<WaterState> pathStack = new Stack();
    int pos = 1;//记录第几种解法

    public static void main(String[] args) {
        MyPot pot = new MyPot();
    }

    //初始化类
    public MyPot() {
        initSpace();
        space[0][0] = 1;//初始状态设置为已访问
        pathStack.add(new WaterState(0, 0, 0));
        dfs(0, 0);
    }

    //输出
    void Output(int pos) {
        System.out.println("第"+pos+"种解决方案:");
        System.out.println("4升水壶    3升水壶    所使用的操作");
        int i = 0;
        int l = pathStack.size();
        while (l>0) {
            System.out.println(pathStack.get(i).x4 + "         " + pathStack.get(i).y3 + "         " + pathStack.get(i).step);
            i++;
            l--;
        }
        System.out.println();
    }

    //深度优先遍历
    void dfs(int x4, int y3) {
        if (x4 == 2) {
            Output(pos);
            pos++;
        }
        else {
            for (int i = 1; i <= 6; i++) {//依次进行六种操作
                WaterState waterState = operate(x4, y3, i);//返回操作后水壶的状态
                if (checkRepeat(waterState.x4, waterState.y3) == 0) {//查重
                    pathStack.add(waterState);//入栈
                    space[waterState.x4][waterState.y3] = 1;//设置为已访问
                    dfs(waterState.x4, waterState.y3);//递归
                    pathStack.pop();//出栈
                    space[waterState.x4][waterState.y3] = 0;//状态重置
                }
            }
        }
    }

    //实现六种操作
    WaterState operate(int x4, int y3, int i) {
        switch (i) {
            case 1:
                x4 = 4;
                break;
            case 2:
                y3 = 3;
                break;
            case 3:
                x4 = 0;
                break;
            case 4:
                y3 = 0;
                break;
            case 5://x->y
                if (x4 + y3 > 3) {
                    x4 = x4 + y3 - 3;
                    y3 = 3;
                } else {
                    y3 = x4 + y3;
                    x4 = 0;
                }
                break;
            case 6://y->x
                if (x4 + y3 > 4) {
                    y3 = x4 + y3 - 4;
                    x4 = 4;
                } else {
                    x4 = x4 + y3;
                    y3 = 0;
                }
                break;
            default:
                break;
        }
        //创建一个WaterState对象返回
        return new WaterState(x4, y3, i);
    }

    //查重
    int checkRepeat(int x4, int y3) {
        if (space[x4][y3] == 1) {
            return 1;
        }
        return 0;
    }

    //状态空间初始化
    void initSpace() {//所有状态初始为0(即未访问)
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 4; j++) {
                space[i][j] = 0;
            }
        }
    }

    //声明一个内部类用来记录水壶操作的状态
    class WaterState {
        int x4;
        int y3;
        int step;//记录进行的是哪一步操作

        WaterState(int x4, int y3, int step) {
            this.x4 = x4;
            this.y3 = y3;
            this.step = step;
        }
    }
}

四、运行结果

在这里插入图片描述


总结

希望我的文章能够帮助到你

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值