015.迷宫回溯问题分析和实现


博主的 Github 地址


1. 迷宫问题说明

  • 图示如下
    pic
  1. 小球得到的路径, 和编程者设置的找路策略有关
    即找路的上下左右的顺序相关
  2. 在得到小球路径时, 可以先使用(下右上左),
    再改成使用(上右下左), 看看路径是否有变化
  3. 测试回溯现象, 求出最短路径

2. 迷宫问题代码实现

2.1. 前要说明

  • 在找路的方法中, 采用策略下右上左的走法进行寻路.
  • 递归的规则就是:
    把墙设为 1, 通路为 2, 不通为 3, 可走为 0,
    因此实际上在进行寻路的时候, 只有 0 的点是可以走的.
    • 从起点开始寻路, 分别按照策略依序向周围四个方向进行寻路.
      即策略是下右上左的话, 则先走下再走右然后走上最后走左
    • 在走向某条路的末端若该点四个方向都走不通,
      则将该点标为不通, 相当于将该点变成墙.
    • 然后退回上一点, 继续测试另外的三个方向,
      直到走通或走不同为止.
    • 最后若能走到终点, 将终点设为 2, 退出递归;
      或者当路线上能走的点全都为 3, 退出递归.

2.2. 迷宫代码

package com.leo9.dc09.maze_question;

public class Maze {
    public static void main(String[] args) {
        //创建一个二维数组, 用以模拟迷宫地图
        int[][] map = new int[8][7];
        //使用1表示墙
        //上下全部置为1
        for(int i = 0; i < 7; i++){
            map[0][i] = 1;
            map[7][i] = 1;
        }
        //左右全部置为1
        for(int i = 0; i < 8; i++){
            map[i][0] = 1;
            map[i][6] = 1;
        }

        //设置挡板, 用1表示
        map[3][1] = 1;
        map[3][2] = 1;
        map[5][2] = 1;
        map[6][2] = 1;

        //输出地图
        System.out.println("===============before=============");
        for(int i = 0; i < 8; i++){
            for(int j = 0; j < 7; j++){
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }

        //开始寻路
        setWay(map,1,1);

        //输出地图
        System.out.println("===============after=============");
        for(int i = 0; i < 8; i++){
            for(int j = 0; j < 7; j++){
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }

    //region 使用递归回溯来给小球找路
    /*
    * @description:
    *   (1) map表示地图
    *   (2) i,j 表示从地图的哪个位置出发, 从(1,1)左上角出发
    *   (3) 如果小球能到map[6][5]位置, 则说明有通路
    *   (4) 约定: 当map[i][j]的值为0表示改点没有走过, 为1表示墙,
    *             为2表示通路可走, 为3表示该点走过但走不通.
    *   (5) 在走迷宫时需要确定策略(方法), 下->右->上->左, 如果该点走不通, 则回溯
    * @param: map 表示地图
    * @param: i 初始位置的行号
    * @param: j 初始位置的列号
    * @return: 如果找到通路返回true, 找不到则返回false
    */
    public static boolean setWay(int[][] map, int i, int j){
        if(map[6][1] == 2){
            //当终点为2时说明走通了
            return true;
        }
        else{
            if(map[i][j] == 0){
                //如果当前点没有走过, 则按照策略 下->右->上->左 的方式走
                //先假定该点可以走通
                map[i][j] = 2;
                if(setWay(map, i + 1, j)){
                    //在这个点基础下向下走, 行数i + 1
                    return true;
                }
                
                else if(setWay(map, i, j + 1)){
                    //在这个点基础下向右走, 列数j + 1
                    return true;
                }

                else if(setWay(map, i - 1, j)){
                    //在这个点基础下向上走, 列数i - 1
                    return true;
                }

                else if(setWay(map, i, j - 1)){
                    //在这个点基础下向左走, 列数j - 1
                    return true;
                }

                else {
                    //如果以上4个条件都不成立, 将该点置成3, 并返回false
                    map[i][j] = 3;
                    return false;
                }
            }
            else{
                //如果map[i][j] != 0, 可能为1, 2, 3
                return false;
            }
        }
    }
    //endregion
}


2.3. 迷宫测试

2.3.1. 起点
  • 起点在(1,1), 如下所示, 是未开始寻路的迷宫

迷宫前

2.3.2. 终点
  • 终点设置在(6,1), 如下所示, 是寻路完后的迷宫

迷宫后

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会为您解答这个问题迷宫问题是指在一个迷宫中,从起点到终点的路径问题。现在我们来看看如何用递归回溯来解决这个问题。 1. 定义状态空间:我们可以用一个二维数组来表示迷宫,其中 0 表示道路,1 表示障碍物,2 表示已经走过的路。 2. 定义决策空间:从当前位置开始,尝试向上、下、左、右四个方向移动,如果该位置合法,则继续往下进行,否则就回溯。 3. 定义终止条件:当到达终点时,就找到了一条路径。 4. 实现递归回溯: ```python def backtrack(maze, row, col, path): # 如果已经到达终点,则直接返回 if row == len(maze)-1 and col == len(maze[0])-1: print(path) return True # 尝试向上、下、左、右四个方向移动 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] for d in directions: n_row, n_col = row + d[0], col + d[1] # 判断当前位置是否合法 if 0 <= n_row < len(maze) and 0 <= n_col < len(maze[0]) and maze[n_row][n_col] == 0: # 如果合法,则标记为已经走过,并继续往下进行 maze[n_row][n_col] = 2 path.append((n_row, n_col)) if backtrack(maze, n_row, n_col, path): return True # 如果不合法,则回溯,将当前位置标记为道路,将当前位置从路径中删除 maze[n_row][n_col] = 0 path.pop() return False maze = [[0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0], [1, 1, 0, 0, 0]] backtrack(maze, 0, 0, [(0, 0)]) ``` 在上述代码中,我们使用一个二维数组 `maze` 来表示迷宫,其中 0 表示道路,1 表示障碍物,2 表示已经走过的路。在 `backtrack` 函数中,我们首先判断当前位置是否已经到达终点,如果是,则找到了一条路径;否则,我们尝试向上、下、左、右四个方向移动,找到合法的位置后,将其标记为已经走过,并继续往下进行。如果到达终点,则返回 True;否则就回溯,将当前位置标记为道路,将当前位置从路径中删除,继续尝试其他方向。在 `maze` 数组中,如果一个位置为 1 表示该位置为障碍物,不能通过;如果一个位置为 2,表示该位置已经走过,不能重复走。 以上就是用递归回溯来解决迷宫问题的过程。在实际应用中,我们可以根据具体问题的特点来定义状态空间、决策空间和终止条件,然后使用递归回溯来求解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值