迷宫最短路用BFS,为什么不能用DFS

举报
yd_275379215 发表于 2026/11/08 08:25:05 2026/11/08
【摘要】 做题时用DFS走迷宫,答案对了但超时;换成BFS立刻过。当时不服气:都是遍历,凭什么差这么多。把两者的搜索过程画在纸上比了一遍,才真正看明白层序展开的意义。核心差异BFS按层扩散:先访问距起点0步的,再1步、2步,第一次到达某点时,走过的步数一定是最短的。DFS一条道走到黑,找到的第一条路径可能绕了远路,必须搜完所有路径才能确认最短,指数级开销。fromcollectionsimportde...

做题时用DFS走迷宫,答案对了但超时;换成BFS立刻过。当时不服气:都是遍历,凭什么差这么多。把两者的搜索过程画在纸上比了一遍,才真正看明白层序展开的意义。

核心差异

BFS按层扩散:先访问距起点0步的,再1步、2步,第一次到达某点时,走过的步数一定是最短的。DFS一条道走到黑,找到的第一条路径可能绕了远路,必须搜完所有路径才能确认最短,指数级开销。

from collections import deque

def shortest_path(grid, start, end):
    """grid中0是通路1是墙,返回起点到终点步数"""
    rows, cols = len(grid), len(grid[0])
    dist = {start: 0}
    q = deque([start])
    while q:
        r, c = q.popleft()
        if (r, c) == end:
            return dist[(r, c)]
        for dr, dc in ((1,0), (-1,0), (0,1), (0,-1)):
            nr, nc = r + dr, c + dc
            if (0 <= nr < rows and 0 <= nc < cols
                    and grid[nr][nc] == 0
                    and (nr, nc) not in dist):
                dist[(nr, nc)] = dist[(r, c)] + 1
                q.append((nr, nc))
    return -1   # 不可达

入队时立刻标记距离,而不是出队时——否则同一节点会被重复入队好几次,队列爆炸。

什么时候BFS不灵

边权不全是1时,「先到即最短」失效:一条绕两步的高速路可能比一条一步的土路更近。这时换Dijkstra(非负权,优先队列每次取当前最近点),再进一步有负权用Bellman-Ford/SPFA。BFS是Dijkstra在所有边权为1时的特例,理解这层关系,选型就不会错。

双向BFS

起点和终点同时扩散,两边碰头即停。搜索空间从b^d降到2·b^(d/2),d为答案深度。无权图上求两点距离,地图一大就值得上这个优化,迷宫游戏里做寻路,双向BFS加边界剪影是常见组合。

DFS的主场

DFS并非不如BFS,是分工不同:要枚举所有路径、回溯找全部解、检测环、拓扑排序、走迷宫「任意一条」路,DFS更顺手且空间只要递归深度。判断标准就一条:要最短且边权相同,选BFS;要遍历所有可能,选DFS加剪枝。当时的超时让我记住了这句话,也顺便记住了队列标记入队时机这个隐蔽的坑。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。