广度优先搜索-迷宫问题

迷宫问题:定义一个矩阵:
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,
要求编程序找出从左上角到右下角的最短路线。
【输入】一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
【输出】左上角到右下角的最短路径,格式如样例所示。
【输入样例】
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
【输出样例】
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
https://www.cnblogs.com/liuyankui163/p/8401183.html

思路:广度遍历是层次遍历,其实这道题问题的关键是如何找出路径,也就是如何存储
走过的路径是关键问题。因为是广度遍历,因此,如果能找到,那么肯定是
最短的路径,但是可能这条路径不是唯一的,所以找出来的路径,可能只是
其中一条最短路径而已,也许有多条最短路径。
这里是path[[row1,col1,index1],[row2,col2,index2],……],
row1,col1都是描述迷宫二维列表的位置,这个不难理解,关键是index1
的理解,是这道题的关键问题。index1表示该点是从path[]列表中的index1
位置走过来的。它记录走过的路径,也就是用path[]列表的下标值来记录每个
点是从哪里走过来的。

python算法实现:
  1 from collections import deque
  2 
  3 # 迷宫二维列表
  4 maze = []
  5 # 对应迷宫的二维列表,0-为访问过,1-访问过
  6 visited = []
  7 # 行数、列数
  8 rows, cols = 0, 0
  9 
 10 
 11 """
 12 path = 
 13 [[0, 0, -1], 
 14 [1, 0, 0], [2, 0, 1], [3, 0, 2], [2, 1, 2], [4, 0, 3], 
 15 [2, 2, 4], [4, 1, 5], [1, 2, 6], [2, 3, 6], [4, 2, 7], 
 16 [0, 2, 8], [2, 4, 9], [0, 3, 11], [1, 4, 12], [3, 4, 12], 
 17 [0, 4, 13], [4, 4, 15]]
 18 第3列的值表示前面这个坐标的点是有path这个列表中第几个位置的顶走过来的。
 19 比如[4, 4, 15],[4,4]这个点是由path[15],这个点[3, 4, 12]走过来的。
 20 """
 21 
 22 
 23 def print_path(path):
 24     # 从列表的最后一个点开始往前找
 25     curNode = path[-1]
 26     real_path = []
 27     # 遍历path,当第3列不是-1,就不是起点,不断遍历
 28     while curNode[2] != -1:
 29         # 把坐标点加入
 30         real_path.append(curNode[0:2])
 31         # path[curNode[2]]表示curNode是由path[]列表中那个位置的点走过来的
 32         curNode = path[curNode[2]]
 33     # 把起点放进去
 34     real_path.append(curNode[0:2])
 35     # 列表反转
 36     real_path.reverse()
 37     # 输出路径的长度
 38     print(len(real_path))
 39     for i in real_path:
 40         print(i)
 41 
 42 
 43 def maze_path():
 44     global maze, visited, rows, cols
 45     visited[0][0] = 1
 46     # 创建一个双向队列
 47     path_queue = deque()
 48     # 从左上角出发,插入队列中
 49     path_queue.append([0, 0, -1])
 50     # 路径列表
 51     path = []
 52     while len(path_queue) > 0:
 53         # 把队列中最左边的元素拿出来,并且移除队列
 54         curNode = path_queue.popleft()
 55         # 把该点加入路径列表
 56         path.append(curNode)
 57         # [0]-行,[1]-列,如果下面条件判断成立,说明走到右下角
 58         if curNode[0] == rows-1 and curNode[1] == cols-1:
 59             # 输出路径
 60             print_path(path)
 61             return True
 62         # 分4个方向前进
 63         # 上,不能访问列表越界,到达的下一个点没有访问过,并且该点的值是0,因为0表示可以走
 64         if curNode[0] - 1 >= 0 and visited[curNode[0]-1][curNode[1]] == 0 and maze[curNode[0]-1][curNode[1]] == 0:
 65             # 存储新点的值,len(path)-1表示该点是从path[]列表的哪个位置过来的
 66             node = [curNode[0] - 1, curNode[1], len(path) - 1]
 67             path_queue.append(node)
 68             # 标记该点访问过了,下次不再访问
 69             visited[curNode[0] - 1][curNode[1]] = 1
 70         #
 71         if curNode[0] + 1 < rows and visited[curNode[0]+1][curNode[1]] == 0 and maze[curNode[0]+1][curNode[1]] == 0:
 72             node = [curNode[0] + 1, curNode[1], len(path) - 1]
 73             path_queue.append(node)
 74             visited[curNode[0] + 1][curNode[1]] = 1
 75         #
 76         if curNode[1] - 1 >= 0 and visited[curNode[0]][curNode[1]-1] == 0 and maze[curNode[0]][curNode[1]-1] == 0:
 77             node = [curNode[0], curNode[1]-1, len(path) - 1]
 78             path_queue.append(node)
 79             visited[curNode[0]][curNode[1]-1] = 1
 80         #
 81         if curNode[1] + 1 < cols and visited[curNode[0]][curNode[1]+1] == 0 and maze[curNode[0]][curNode[1]+1] == 0:
 82             node = [curNode[0], curNode[1]+1, len(path) - 1]
 83             path_queue.append(node)
 84             visited[curNode[0]][curNode[1]+1] = 1
 85     else:
 86         print("没有可以到达的路径!")
 87         return False
 88 
 89 
 90 def main():
 91     global maze, visited, rows, cols
 92     rows, cols = map(int, input().split())
 93     for i in range(rows):
 94         temp = list(map(int, input().split()))
 95         maze.append(temp)
 96     # [[0, 1, 0, 0, 0], [0, 1, 0, 1, 0],
 97     #  [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0]]
 98     visited = [[0 for i in range(cols)] for i in range(rows)]
 99     maze_path()
100 
101 
102 if __name__ == '__main__':
103     main()

 

 
posted @ 2020-07-19 12:37  StudyNLP  阅读(541)  评论(0编辑  收藏  举报