用一个h行w列的int[][]类型二维数组实例表示一个迷宫(由变量maze引用),左上角的maze[0][0]是迷宫的入口,右下角的maze[h-1][w-1]是迷宫的出口。问题如下:
- 如果规定每次只能向右或向下移动一步,你能否用回溯法找出迷宫的所有路径?
- 如果把maze中的一些值替换成-1表示墙壁,应该如何修改代码使其继续可以工作?
初始化
首先,创建一个方法用于初始化一个二维数组:
/*
初始化一个二维数组,用0填充
*/
public int[][] initialArray(int hight, int weigh) {
int maze[][] = new int[hight][weigh];
for (int i = 0; i < hight; i++)
for (int j = 0; j < weigh; j++)
maze[i][j] = 0;
return maze;
}
其次,创建一个用于存储当前行列位置的类
public class Route {
public int row;
public int col;
public Route(int row, int col) {
this.row = row;
this.col = col;
}
}
最后创建一个用于输出结果的类
/*
输出结果
*/
public void printResult(List<List<Route>> paths){
for (var path : paths) {
for (var p:path){
System.out.printf("[%d,%d],",p.row,p.col);
}
System.out.println();
}
}
问题一
使用回溯法解决,结构为(修改->递归->恢复)
public void question1(int[][] maze, Route route, Stack<Route> path, List<List<Route>> paths) {
var rowLength = maze.length;//获取数组有多少行
var colLength = maze[0].length;//获取数组有多少列
if (route.row > rowLength - 1 || route.col > colLength - 1) return;//防御
path.push(route);//入栈(修改)
if (route.row == rowLength - 1 && route.col == colLength - 1)
paths.add(new ArrayList<>(path));//找到终点后添加路径
if (route.row < rowLength)//向下走
question1(maze, new Route(route.row + 1, route.col), path, paths);//递归
if (route.col < colLength)//向右走
question1(maze, new Route(route.row, route.col + 1), path, paths);//递归
path.pop();//出栈(恢复)
}
通过以下代码实现
public static void main(String[] args) {
Homework hm = new Homework();
var maze = hm.initialArray(3, 3);
var paths = new ArrayList<List<Route>>();
hm.question1(maze, new Route(0, 0), new Stack<>(), paths);
hm.printResult(paths);
结果如下
问题二
将问题一稍作修改,添加一个判断-1为墙壁的条件即可
public void question2(int[][] maze, Route route, Stack<Route> path, List<List<Route>> paths) {
var rowLength = maze.length;//获取数组有多少行
var colLength = maze[0].length;//获取数组有多少列
if (route.row > rowLength - 1 || route.col > colLength - 1) return;//防御
path.add(route);//入栈(修改)
if (route.row == rowLength - 1 && route.col == colLength - 1)
paths.add(new ArrayList<>(path));//找到终点后添加路径
if (route.row < rowLength && maze[route.row][route.col] != -1)//判断当前位置是否墙壁,若不是即向下走
question2(maze, new Route(route.row + 1, route.col), path, paths);//递归
if (route.col < colLength && maze[route.row][route.col] != -1)//判断当前位置是否墙壁,若不是即向右走
question2(maze, new Route(route.row, route.col + 1), path, paths);//递归
path.pop();//出栈(恢复)
}
通过以下代码实现
public static void main(String[] args) {
int [][] maze={
{0,0,0},
{0,-1,0},
{0,0,0}
};
Homework hm=new Homework();
var paths = new ArrayList<List<Route>>();
hm.question2(maze,new Route(0,0),new Stack<>(),paths);
hm.printResult(paths);
}
结果如下