作者在“拯救大兵瑞恩”时遇到的问题小记——迷宫最短路径

本文介绍了一种使用深度优先搜索(DFS)算法解决迷宫中寻找特定目标(即瑞恩)的最短路径问题的方法。通过定义迷宫状态、方向向量、标记已访问位置以及递归遍历所有可能的方向,算法能够找到从起点(1,1)到目标点(p,q)的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

约翰·米勒上尉接到上级命令,要去一个迷宫拯救被困其中的大兵瑞恩。迷宫由空地格子和障碍物——墙组成。现在米勒从(1,1)这个地方降落并进入迷宫,问找到瑞恩的最短路径。通过卫星定位到瑞恩所在坐标为(p, q)处,让你求解。

代码

/**
 * 约翰·米勒上尉接到上级命令,要去一个迷宫拯救被困其中的大兵瑞恩。
*迷宫由空地格子和不可穿透的墙组成。现在米勒从(1,1)这个地方降落并进入迷宫,问找到瑞恩的最短路径。
*通过卫星定位到瑞恩所在坐标为(p, q),让你求解。
 * @author XZP
 *
 */
public class SavingToRyan {
	// 给定一个迷宫,1表示墙,0表示空地
	public static int[][] maze = {
			{0, 0, 1, 0},
			{0, 0, 0, 0},
			{0, 0, 1, 0},
			{0, 1, 0, 0},
			{0, 0, 0, 1}
	};
	// 初始化一个控制方向的向量
	public static int[][] direction = {
			{0, 1}, // 左
			{1, 0}, // 下
			{0, -1}, // 右
			{-1, 0}  // 上
	};
	public static int[][] book = new int[5][4]; // 用于标记该格子是否走过
	// 迷宫的行列
	public static int row = 5;
	public static int col = 4;
	// 米勒出发的坐标x,y
	public static int startx = 1; 
	public static int starty = 1;
	// 瑞恩被困的位置p,q
	public static int p = 4;
	public static int q = 3;
	// 初始化一个全局变量保存最短路径
	public static int min = Integer.MAX_VALUE;
	public static void main(String[] args) {
		book[0][0] = 1;
		dfs(1, 1, 0);
		System.out.println("救出瑞恩的最短路径为:" + min);
	}
	public static void dfs(int x, int y, int step) {
		int nx, ny;
		// 首先是当前的状态
		if (x == p && y == q) { // 找到瑞恩
			if (step < min) {
				min = step;
				System.out.println("x:" + x + " y:" + y + " p:" + p + " q:" + q + " step:" + step);
			}
			return;
		}
		System.out.println("x:" + x + " y:" + y);
		for (int k = 0; k < 4; k++) {
			nx = x + direction[k][0]; // 下一步的x,y值
			ny = y + direction[k][1];
			if (nx < 1 || nx > 5 || ny < 1 || ny > 4) {
				continue;
			}
			if (book[nx-1][ny - 1] == 0 && maze[nx - 1] [ny -1] == 0) { // 在迷宫内且没有障碍物,没有走过
				book[nx - 1][ny -1] = 1; // 这步很重要,如果没有就会栈溢出 ----------------------------     (1)
				dfs(nx, ny, step + 1);
				book[nx - 1][ny - 1] = 0; // 回退到这步要将其重新标记为能走的  ----------------------- (2)
			}
		}
	}
}

注意

作者因为一时疏忽,漏掉了注释(1)处对应的那行代码,于是测试的时候栈溢出,反复理了一下逻辑,都觉得没问题,再三跟踪调试之后,发现自己犯了一个低级错误:死递归。
如果不要注释(1)对应的代码,就会在下一步的格子中递归回来(这个应该比较好理解),如此往复!
那顺带说一下注释(2)对应的代码,就是尝试完(nx-1, ny - 1)对应的点之后需要将这个标记拿掉。有点绕,很多问题在这两步时最难理解!!!!故特别记录,以便加深自己的理解和运用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值