题目
给定一个矩阵,元素的取值只有0和1。
我们用这样的一个矩阵表示迷宫:1代表墙壁,0代表可以人走的路。
左上角为入口,右下角为出口。
问题:根据输入的矩阵,寻找一条从入口到出口的路线。
例如:
输入
0, 1, 0, 0, 0,
0, 1, 1, 1, 1,
0, 1, 0, 1, 1,
0, 0, 0, 0, 1,
1, 0, 1, 0, 0,
对应的输出可能为(“#”表示经过的路线)
#, 1, 0, 0, 0,
#, 1, 1, 1, 1,
#, 1, 0, 1, 1,
#, #, #, #, 1,
1, 0, 1, #, #,
分析
解题思路
深度优先搜索:优先往某一个方向不断深入搜索。比如先往左搜索,如果左侧还能继续搜索下去,那继续往左侧深入搜索,直到左侧不能再深入了,再换个方向,往换的方向继续深入搜索。
从起点开始,从上下左右四个方向深度优先搜索,探索可能的行进路线。如果走到了终点,表明已经找到从入口到出口的路线,则停止搜索。
解答
import unittest
import numpy as np
def print_maze(maze_map: np.array):
"""打印出行走路线"""
shape = maze_map.shape
print("一种迷宫走法:")
for i in range(shape[0]):
for j in range(shape[1]):
if maze_map[i][j] == 8:
print(f"#, ", end="")
else:
print(f"{maze_map[i][j]}, ", end="")
print(f"\n")
def can_move(maze_map: np.array, x, y, direction) -> bool:
"""
处在(x,y)位置,检查是否可以往direction所指示的方向行进
:param maze_map:
:param x: 行位置
:param y: 列位置
:param direction: 方向,分别使用1,2,3,4来表示上下左右。
:return: 是否可以行进
"""
shape = maze_map.shape
# 这些条件判断,一定要小心核对,如果粗心写错,且意识不到哪里写错了,
# 在递归调用的场景下,很难通过调试找到原因。
# 可以往上走
if direction == 1 and x > 0 and maze_map[x-1][y] == 0:
return True
# 可以往下走
if direction == 2 and x+1 < shape[0] and maze_map[x+1][y] == 0:
return True
# 可以往左走
if direction == 3 and y > 0 and maze_map[x][y-1] == 0:
return True
# 可以往右走
if direction == 4 and y+1 < shape[1] and maze_map[x][y+1] == 0:
return True
# 其他情况,走不了
return False
def move(maze_map: np.array, x, y, direction) -> (int, int):
"""处在(x,y)位置,往direction所指示的方向行进一步"""
x1 = x
y1 = y
if direction == 1:
x1 -= 1
if direction == 2:
x1 += 1
if direction == 3:
y1 -= 1
if direction == 4:
y1 += 1
return x1, y1 # 返回新的位置(坐标)
def walk_maze(maze_map: np.array, x0, y0, x1, y1):
maze_map[x0][y0] = 8
for direction in range(1, 5): # 从上下左右四个方向进行探索
if can_move(maze_map, x0, y0, direction): # 此方向可以行进
cur_x, cur_y = move(maze_map, x0, y0, direction) # 往这个方向行进一步
maze_map[cur_x][cur_y] = 8 # 标记该点已经走过
if cur_x == x1 and cur_y == y1:
print_maze(maze_map)
# return # 如果想探索各种走出迷宫的路线,则不要注释该句。
walk_maze(maze_map, cur_x, cur_y, x1, y1)
# 回溯,非常重要!探索其他方向时,对上一个方向探索的走过标记进行恢复。
maze_map[cur_x][cur_y] = 0
# 以下为测试代码,验证程序的正确性
class Test(unittest.TestCase):
def test_case1(self):
maze_map = np.array(
[
[0, 1, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 1, 0, 1, 1],
[0, 0, 0, 0, 1],
[1, 0, 1, 0, 0],
],
dtype=np.int32)
walk_maze(maze_map, 0, 0, 4, 4)