Java数据结构-迷宫回溯问题 蓝桥必备

前言:

        鸽了一天之后的博主,今天终于良心发现,打开了尘封的博客,给大家带来了今天的博客

         今天我要介绍的是什么呢,故名思议,迷宫回溯问题,迷宫回溯问题其实相当于是对递归回溯深度理解,将前面我发的八皇后问题理解通透后回头再看看迷宫回溯问题,嗯?这不是有手就行吗!

        那跟随着博主的脚步,从 迷宫问题的概述 -> 迷宫问题的思路分析 -> 迷宫问题的代码实现与分析 -> 总结 开始学习我们的迷宫回溯问题吧!

        如果喜欢博主记得点赞哦,如果可以的话,给博主一个小小的关注.

往期精彩:

        八皇后问题


🚗迷宫回溯问题的概述:

 定义

        在一个迷宫中,我们要通过我们的程序,让一个小球在起点出发,绕过重重障碍,找到出口,这就是著名的迷宫问题.

 重要性

        在本届蓝桥杯备赛中,作为c++的B组(我报错了,别问我为什么不说Java),显赫的提出了迷宫回溯问题!除了在大赛中出现,迷宫回溯问题也是我们更好的理解递归和回溯的重要途经.


🛹迷宫回溯问题的思路: 

  • 首先:我们要做的第一步就是创建一个迷宫,我们可以通过二维数组去实现
  • 其次:我们要做出某些约定 如下
  • 1) 1表示围墙 2) 2表示已经走过的通路 3)3表示此路不通 4) 0表示该路没有走过
  • 创建一个回溯方法去找路
  • 制定一个策略(本人采用的是 下 → 右 → 上 → 左)

🦽代码实现: 

  • 创建一个迷宫 
 var maze = new int[8][7];
        for (int i = 0; i < maze.length; i++) {
            maze[i][0] = 1;
            maze[i][6] = 1;
        }
        for (int i = 0; i < maze[0].length; i++) {
            maze[0][i] = 1;
            maze[7][i] = 1;
        }
        maze[3][1] = 1;
        maze[3][2] = 1;
        maze[3][3] = 1;
        for(var arr : maze) {
            for(var ele : arr) {
                System.out.print(ele + " ");
            }
            System.out.println();
        }

代码分析:

  • 第一个for循环的目的是创建两列围墙,如图所示

 

  • 第二个for是的目的是创建两行围墙,如图所示

  • 下面的赋值是为了增加障碍,这个可按个人的喜好增加,本人加过的障碍如图所示 

 

  •  创建一个方法去走
public static boolean searchRood(int[][] maze,int srcRow,int srcCol) {
        if(maze[6][5] == 2) {
            return true;
        }
        if(maze[srcRow][srcCol] == 0) {
            maze[srcRow][srcCol] = 2;
            if(searchRood(maze,srcRow+1,srcCol)) {
                return true;
            }else if(searchRood(maze,srcRow,srcCol+1)) {
                return true;
            }else if(searchRood(maze,srcRow-1,srcCol)) {
                return true;
            }else if(searchRood(maze,srcRow,srcCol-1)) {
                return true;
            }else {
                maze[srcRow][srcCol] = 3;
            }
        }
        return false;
    }

代码分析:

  • maze传递的是二维数组,即迷宫,因为数组是对象,存放在堆内存空间,有利于多个方法同时对该数组作出修改
  • srcRow与SrcCol为开始的坐标 
  • 第一个判断的目的是,如果终点被标识了2,说明终点已经到了,方法结束
  • 第二个判断是没有走过的情形,由下图分析代码目的:(建议边看代码边看图,图是根据代码实现的,且我们需要培养假设的思想)

 

 

  •  结合两个图一起看,最后是可以光所有的栈的
  • 注意:1表示围墙,不能走,弹栈  2表示已经走过,没必要走,弹栈 3表示死路,不能走,弹栈 

完整代码

package datastructure.chapter02.recursion.maze;

public class MazeBackTrackingDemo {

    public static void main(String[] args) {
        var maze = new int[8][7];
        for (int i = 0; i < maze.length; i++) {
            maze[i][0] = 1;
            maze[i][6] = 1;
        }
        for (int i = 0; i < maze[0].length; i++) {
            maze[0][i] = 1;
            maze[7][i] = 1;
        }
        maze[3][1] = 1;
        maze[3][2] = 1;
        maze[3][3] = 1;
        for(var arr : maze) {
            for(var ele : arr) {
                System.out.print(ele + " ");
            }
            System.out.println();
        }
        searchRood(maze,1,1);
        System.out.println();
        for(var arr : maze) {
            for(var ele : arr) {
                System.out.print(ele + " ");
            }
            System.out.println();
        }
    }

    /**
     * 小球找路的方法
     * @param maze 迷宫所对应的二维数组
     * @param srcRow 起点所对应的行
     * @param srcCol 起点所对应的列
     * @return 用于判断递归的条件
     */
    public static boolean searchRood(int[][] maze,int srcRow,int srcCol) {
        if(maze[6][5] == 2) {
            return true;
        }
        if(maze[srcRow][srcCol] == 0) {
            maze[srcRow][srcCol] = 2;
            if(searchRood(maze,srcRow+1,srcCol)) {
                return true;
            }else if(searchRood(maze,srcRow,srcCol+1)) {
                return true;
            }else if(searchRood(maze,srcRow-1,srcCol)) {
                return true;
            }else if(searchRood(maze,srcRow,srcCol-1)) {
                return true;
            }else {
                maze[srcRow][srcCol] = 3;
            }
        }
        return false;
    }

}

 


🚓总结: 

        迷宫回溯问题总体代码量仍是很少的,对代码的解析主要在图中,想要真正理解其中的回溯思想,还是得自己也尝试动手画一下内存图

        总结一下必须掌握的几点:理解回溯和递归的场景

🚇下一站:单向链表

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爪哇土著、JOElib

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值