zoukankan      html  css  js  c++  java
  • 广度优先搜索-迷宫问题

    迷宫问题:定义一个矩阵:
    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()
     
  • 相关阅读:
    \r,\n,\r\n的区别
    \r,\n,\r\n的区别
    C# TextBox 换行 滚动到最后一行
    C# TextBox 换行 滚动到最后一行
    C# Textbox 始终保持最后最后一行
    C# Textbox 始终保持最后最后一行
    踩坑之mongodb配置文件修改
    踩坑之mongodb配置文件修改
    开启mongodb 的web
    开启mongodb 的web
  • 原文地址:https://www.cnblogs.com/an-wl/p/13339319.html
Copyright © 2011-2022 走看看