超详解的迷宫问题(Java版)
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超详解的迷宫问题(Java版)相关的知识,希望对你有一定的参考价值。
问题描述
给定一个M*N 的迷宫图、入口与出口、行走规则。求一条从指定入口到出口的路径(这里M=8,N=8),所求路径必须是简单路径,即路径不重复
(为了方便算法起见,在整个迷宫外围加上一堵墙)
算法实现
use Stack
从入口 (i, j) 出发,共有 上(i-1, j)下(i+1, j)左(i, j-1)右(i, j+1)四个方向选择
考虑使用栈,从当前位置分别向四个方向寻找,可行的点,如果有可行的点就入栈,若无可行的点,则将栈顶的元素 pop 修改 值为 -1 代表不可行。
代码展示
import java.util.Stack;
public class 迷宫问题 {
static int[][] matrix;
public static void main(String[] args) {
// 1 代表围墙,2代表走过,-1代表该点不通,避免下次重复搜索
matrix = new int[][] {
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
// 初始化栈
Stack<int[]> stack = new Stack<>();
// 初始化四个方向 上下左右
int[] x = {-1, 1, 0, 0};
int[] y = {0, 0, -1, 1};
// (1,1)作为起点
stack.push(new int[]{1, 1});
// 修改(1,1)的值为 2,代表已经走过
matrix[1][1] = 2;
printResult();
while (!stack.isEmpty()) { // 栈不为空就一直循环
int[] cur = stack.peek(); // 获取当前点,cur[0]:代表 横坐标 cur[1]:代表纵坐标
// 到达终点
if (cur[0] == 8 && cur[1] == 8) {
printResult();
break;
}
// 从当前点向四个方向找可行的点
int i;
for (i = 0; i < 4; i++) {
int row = cur[0]+x[i];
int column = cur[1]+y[i];
// 判断当前方向是否可以通过
if (matrix[row][column] == 0) {
stack.push(new int[]{row, column});
matrix[row][column] = 2;
break;
}
}
// 如果未找到可行方向,则将栈顶元素 pop,修改为 -1
if (i == 4) {
cur = stack.pop();
matrix[cur[0]][cur[1]] = -1;
}
}
}
// 输出迷宫图,显示路线
public static void printResult() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j]+" ");
}
System.out.println();
}
}
}
recursion
使用递归每次都向四个方向探索,若某条路不通,则回溯,并修改该点值为-1,反之修改2,代表走过的路。
代码展示
package Algorithm;
import java.util.Stack;
public class 迷宫问题 {
static int[][] matrix;
public static void main(String[] args) {
// 1 代表围墙,2代表走过,-1代表该点不通,避免下次重复搜索
matrix = new int[][] {
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
// 起点 (1,1)终点(8,8),可以灵活设置
recursion(1, 1);
printResult();
}
// 递归方法
public static boolean recursion(int i, int j) {
// 递归结束条件,代表已到达终点(8,8)
if (matrix[8][8] == 2) {
return true;
}
// 判断4个方向是否可行,一个方向可行就往深度递归,否则:回溯
if (matrix[i][j] == 0) { // 如果该点未访问过,则从该点探索
matrix[i][j] = 2;
if (recursion(i-1, j)) { // 如果上方可行,则继续探索
return true;
} else if (recursion(i+1, j)) { // 下方
return true;
} else if (recursion(i, j-1)) { // 左方
return true;
} else if (recursion(i, j+1)) { // 右方
return true;
} else { // 如果四个方向 都不行说明该递归分支,不行,回溯
// 该点走不通,标记 -1,避免重复访问
matrix[i][j] = -1;
return false;
}
} else {
return false;
}
}
// 输出迷宫图,显示路线
public static void printResult() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j]+" ");
}
System.out.println();
}
}
}
感谢
技术开源,知识共享,分享快乐
站在巨人的肩膀上,前进!
小白梦想当大牛
加油!
以上是关于超详解的迷宫问题(Java版)的主要内容,如果未能解决你的问题,请参考以下文章
详解Java递归(Recursion)通过递归解决迷宫回溯及八皇后问题