网格图题单 DFS BFS 网格图题目 图论 灵茶山艾府 灵神 灵神题单

小小贪吃蛇,移动花样多。
平移加旋转,为把迷宫破。
代码复代码,bug 何其多。
六步化一步,AC 定我夺。
—— 1210. 穿过迷宫的最少移动次数

一、网格图 DFS

适用于需要计算连通块个数、大小的题目。

部分题目做法不止一种,也可以用 BFS 或并查集解决。

二叉树 DFS 与网格图 DFS 的区别:

二叉树网格图
递归入口根节点网格图的某个格子
递归方向左儿子和右儿子一般为左右上下的相邻格子
递归边界空节点(或者叶节点)出界、遇到障碍或者已访问

模板(计算每个连通块的大小):

Python3
Java
C++
Go
# 返回网格图 grid 每个连通块的大小
# 时间复杂度 O(mn)
def dfsGrid(grid: List[List[str]]) -> List[int]:
    m, n = len(grid), len(grid[0])
    vis = [[False] * n for _ in range(m)]

    # 返回当前连通块的大小
    def dfs(i: int, j: int) -> int:
        vis[i][j] = True
        size = 1
        for x, y in (i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j):  # 左右上下
            # 这里 grid[x][y] == '.' 根据题意修改
            if 0 <= x < m and 0 <= y < n and grid[x][y] == '.' and not vis[x][y]:
                size += dfs(x, y)
        return size

    comp_size = []
    for i, row in enumerate(grid):
        for j, ch in enumerate(row):
            if ch != '.' or vis[i][j]:  # ch != '.' 根据题意修改
                continue
            size = dfs(i, j)
            comp_size.append(size)
    return comp_size

思维扩展

二、网格图 BFS

适用于需要计算最短距离(最短路)的题目。

DFS 是不撞南墙不回头;BFS 是往水塘中扔石头(起点),荡起一圈圈涟漪(先访问近的,再访问远的)。

模板(单源最短路):

Python3
Java
C++
Go
# 返回从 (start_x, start_y) 出发,到其余格子的最短距离
# 时间复杂度 O(mn)
def bfsGrid(grid: List[List[str]], start_x: int, start_y: int) -> List[List[int]]:
    m, n = len(grid), len(grid[0])
    dis = [[-1] * n for _ in range(m)]

    dis[start_x][start_y] = 0
    q = deque([(start_x, start_y)])

    while q:
        i, j = q.popleft()
        for x, y in (i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j):  # 左右上下
            # 这里 grid[x][y] == '.' 根据题意修改
            if 0 <= x < m and 0 <= y < n and grid[x][y] == '.' and dis[x][y] < 0:
                dis[x][y] = dis[i][j] + 1
                q.append((x, y))

    return dis

三、网格图 0-1 BFS

边权只有 的题目,也可以用 BFS 做。

四、网格图 Dijkstra

图论题单 中的「§3.1 单源最短路:Dijkstra 算法」,我标记了网格图的题目。

五、综合应用

思考题

  1. 对于 列的网格图,BFS 的队列最多消耗多少空间?DFS 的递归栈最多消耗多少空间?
  2. 构造一个网格图,让 DFS 的递归深度尽量大。如果起点是 要如何构造?如果起点是 要如何构造?

欢迎在评论区发表你的思路。

算法题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
  7. 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

如果你发现有题目可以补充进来,欢迎评论反馈。

评论 (99)