X16数据结构部分05

递归解决迷宫问题
本文探讨了如何使用递归调用来解决迷宫问题。首先分析了递归调用在打印问题中的应用,随后详细讲解了迷宫问题的递归实现,提供了具体的算法思路和步骤。最后给出了内容的总目录。

递归调用打印问题

	/*
    递归能够解决什么样的问题呢
        阶乘 8皇后 魔攻问题 最短路径问题

        举个例子 球和篮子
        如果是两个球放到两个篮子里面
        就是3种结果(1 1)(2 0)(0 2)

        像快速排序 二分查找 归并排序等算法都需要用到递归

    递归需要遵循的重要规则
        方法区内存是独立的,不受外部影响
        如果递归的是引用数据类型,那么引用指向的数据将会被共享
        如果无限递归,则会出现栈溢出异常java,lang.StackOverflowError
        所以需要向递归的条件边界趋近
     */
	public static void main(String[] args) {
        test(6);
    }

    private static void test(int i) {
        if (i > 1){
            test(i - 1);
        }
        System.out.print(i + " "); // 1 2 3 4 5 6
    }
    /*
    打印规则递归调用规则
    使用栈模拟递归调用
        方法栈帧首先指向main
        每调用依次方法
        都会在栈帧上方开辟新的空间
        一直开辟到test(1)
        此时栈帧指向test(1)

        然后开始在栈顶调用System.out.print方法
        因为每一个方法都会等内部的方法执行结束后再去执行下一行代码
        直到main方法上面的栈帧执行完毕

        main方法栈帧指向的test方法才算执行完毕
        接着就可以执行test方法的下一个方法了
     */

迷宫问题递归实现

/**
 * class maze
 *
 * @author 404 little dinosaur
 */
class Maze{
    /*
    需求:
        小球从初始值[1][1]开始出发
        寻找出口[6][5]
        找到最短路径
        小球走过的路用2表示
        并输出每次小球走过的坐标
        返回能否到达出口
     */
    public static void main(String[] args) {
        /*
        二维数组模拟迷宫
         */
        int[][] maze = new int[8][7];
        /*
        使用1模拟墙
        边界部分围上墙
         */

        /*
        最上面和最下面围成墙
         */
        for (int i = 0; i < 7; i++) {
            maze[0][i] = 1;
            maze[7][i] = 1;
        }
        /*
        最左边和最右边围成墙
         */
        for (int i = 0; i < 6; i++) {
            maze[i][0] = 1;
            maze[i][6] = 1;
        }
        /*
        中间有一堵墙
         */
        maze[3][1] = 1;
        maze[3][2] = 1;
        /*
        输出迷宫情况
         */
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(maze[i][j] + " ");
            }
            System.out.println();
        }
        /*
        给小球找通路
         */
        boolean lookForExit = lookForExit(maze, 1, 1, 6, 5);
        System.out.println(lookForExit); // true
        System.out.println();
        /*
        输出标识后的地图
         */
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(maze[i][j] + " ");
            }
            System.out.println();
        }
    }

    /**
     * 使用递归回溯来给小球找路
     * @param maze 地图
     * @param x 小球的横坐标
     * @param y 小球的纵坐标
     * @param x1 出口横坐标
     * @param y1 出口纵坐标
     * @return 是否找到出口
     */
    private static boolean lookForExit(int[][] maze,int x,int y,int x1,int y1){
        /*
        实现思路:
            探索过的点使用3表示
            可以保证回溯的时候不会重复探索
            玩迷宫是有策略的
            如果出现3个方向
            需要一条一条探索

            如果走不通
            再回到分叉点
            走另外一条路
            直到走通为止

            在程序中
            一共有四条路可以探索 下上左右
            最终走出来的路线与探索顺序有密切联系
         */
        if (maze[x1][y1] == 2){
            /*
            程序运行到此处
            说明找到通路
            返回真
             */
            return true;
        }else{
            /*
            程序运行到此处
            说明递归正在按顺序找通路
            此时再次探索会有如下几种情况
            0 1 2 3
            需要分情况讨论
             */
            if (maze[x][y] == 0){
                /*
                程序运行到此处
                说明这条路可以走
                maze[x][y] = 2;
                这句代码每次递归都会执行到
                假设这条路可以走
                 */
                maze[x][y] = 2;
                if (lookForExit(maze,x + 1,y,x1,y1)){   // 向下走
                    /*
                    程序运行到此处
                    说明这条递归可以继续递归
                    小球继续探索下面这条路
                     */
                    return true;
                }else if (lookForExit(maze, x, y + 1, x1, y1)){ // 向右走
                    return true;
                }else if (lookForExit(maze, x - 1, y, x1, y1)){ // 向上走
                    return true;
                }else if (lookForExit(maze, x, y - 1, x1, y1)){ // 向左走
                    return true;
                }else{
                    /*
                    程序运行到此处
                    说明这是一条死路
                    走不通
                    标记为3
                    小球不会走这条路
                     */
                    maze[x][y] = 3;
                    return false;
                }
            }else {
                /*
                程序运行到此处
                说明这个点是1 2 3
                这个时候运行到此处的
                递归退出程序
                 */
                return false;
            }
        }
    }
    /*
    另外一种情况
        我们在第2行第3列的位置放上挡板
        我们在第3行第3列的位置放上挡板
        然后运行
        发现是2个3
        说明整条路通往死胡同
        最里面的点到分叉点一路
        都会被标记为3
        思考:如何求最短路径
        	把所有的策略用数组表示出来
            然后把每个策略得到的节点进行统计
            地图中2长度最少的就是最短路径的策略
     */
}

总目录

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

muskfans

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

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

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

打赏作者

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

抵扣说明:

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

余额充值