Hello,我是 Alex 007,一个热爱计算机编程和硬件设计的小白,为啥是007呢?因为叫 Alex 的人太多了,再加上每天007的生活,Alex 007就诞生了。 最近有一位小学妹 Coco 入坑了算法,没有跟着老师正规的学习,而是自己走的野路子,一些解题方式确实把我雷到了,来看一下小学妹是怎么解决迷宫问题的。 先来看一下题目吧,所谓的迷宫其实就是一个二维列表,其中的1表示墙壁,0表示空地,之恩给你横着后或者竖着走,不能斜着走。 简单粗暴的方法,你也不能说人家做的是错的,实践出真知,至少结果是对的,但是姑娘,你怕是没遭受迷宫问题的毒打吧。 虽然方法不敢苟同,但至少迷宫图可以拿过来用一下: 对于迷宫问题,在算法中通常有两种解决方案,一种是深度优先搜索(Depth First Search),另一种是广度优先搜索(Breadth First Search)。 暂且不论两种搜索算法的适用场景和优劣,我们先来看一下到底该怎么搜索。 计算机并没有我们想象的那么聪明,它解决问题的方法目前为止只有一个,那就是暴力枚举,所谓的各种算法只不过是通过逻辑或者计算减少一些无意义枚举。 在迷宫问题中,计算机搜索的具体实现就是通过不断尝试不同的方向,结合题意,从某个位置开始出发有四个方向可选择,也就是上下左右,但是在走之前,要先判断能不能走,也就是下一步有没有墙存在,还要判断下一步有没有走过,如果以前已经走过的话,那就没必要再走了。 而在二维列表中,所谓的上下左右走,不过就是索引的变换,因此我们可以先定义一下四个方向的计算函数: 大致了解了计算机搜索的方式之后,我们再来具体看一下两种搜索算法。 所谓是深度优先搜索,顾名思义,就是不到黄河心不死,找到一条路之后,我就一条道走到黑,如果实在没有地方可以继续往下走了,我才往后退,并且把走过的这条路标上“此路不通”。 往后退到除了刚才尝试过的路径还有其它选项的位置,再尝试下一个路径,如此重复,可以将迷宫中所有能走的位置都走一遍,直到某一条路径能够到达终点为止。 输出结果为: 不相信的小伙伴可以像Coco一样,自己按照路线走一下试试。 广度优先搜索,顾名思义,就是多管齐下,广泛搜索,从某一个位置出发,将所有可以走到的位置存储在队列中,然后一一尝试新的位置,在新的位置中继续判断下一步可以到达的位置,在记录路径的时候,可以开一个列表存储走过的每一步,同时要记录这一步是从哪一步迈出的。 输出结果为: 而且,广度优先搜索还有一个好处,它搜索到的路径一定是最短路径,因此它是一层一层搜索的,只要到底了目标就立刻返回。 最后我们通过一张图来看一下深度优先搜索和广度优先搜索: 完整代码放在了我的GitHub上,喜欢的小伙伴欢迎Star哦!
1.题目描述
[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]
2.解题思路
directions = [ lambda x, y: (x + 1, y), lambda x, y: (x - 1, y), lambda x, y: (x, y + 1), lambda x, y: (x, y - 1), ]
3.深度优先搜索
DFS
def findMazePath(startX, startY, endX, endY): # 用于记录路径 pathStack = [(startX, startY)] while pathStack: current = pathStack[-1] # 如果当前节点就是终点 if current[0] == endX and current[1] == endY: for path in pathStack: print(path, end=" -> ") print("bingo!") return True directions = [ lambda x, y: (x + 1, y), lambda x, y: (x - 1, y), lambda x, y: (x, y + 1), lambda x, y: (x, y - 1), ] for direction in directions: nextStep = direction(current[0], current[1]) # 如果下一个节点可以走 if maze[nextStep[0]][nextStep[1]] == 0: # 1.添加到路径中 pathStack.append(nextStep) # 2.标记为已走过 maze[nextStep[0]][nextStep[1]] = 2 break else: # 如果for循环正常执行完,说明无路可走,路径中弹出刚才的路线 pathStack.pop() else: print('NO PATH TO THROUGH MAZE') return False
(1, 1) -> (2, 1) -> (3, 1) -> (4, 1) -> (5, 1) -> (5, 2) -> (5, 3) -> (6, 3) -> (6, 4) -> (6, 5) -> (7, 5) -> (8, 5) -> (8, 6) -> (8, 7) -> (8, 8) -> bingo!
4.广度优先搜索
BFS
def findMazePath(startX, startY, endX, endY): queue, path = deque(), [] queue.append((startX, startY, -1)) while queue: # 取出当前所在位置 current = queue.popleft() path.append(current) # 如果当前节点是终点 if current[0] == endX and current[1] == endY: printPath(path) return True directions = [ lambda x, y: (x + 1, y), lambda x, y: (x - 1, y), lambda x, y: (x, y + 1), lambda x, y: (x, y - 1), ] # 遍历四个方位的节点 for direction in directions: nextStep = direction(current[0], current[1]) # 如果下一个节点可以走 if maze[nextStep[0]][nextStep[1]] == 0: # 1.记录路径和父节点 queue.append((nextStep[0], nextStep[1], len(path) - 1)) # 2.标记为已走过 maze[nextStep[0]][nextStep[1]] = 2 else: print('NO PATH TO THROUGH MAZE') return False
(1, 1) -> (2, 1) -> (3, 1) -> (4, 1) -> (5, 1) -> (5, 2) -> (5, 3) -> (6, 3) -> (6, 4) -> (6, 5) -> (7, 5) -> (8, 5) -> (8, 6) -> (8, 7) -> (8, 8) -> bingo!
5.总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算