PrepStack · Markdown HTML

网格 DP

动态规划 · HTML

数学 / 逻辑形态

dp[r][c] 表示到达 (r,c) 或从其出发的答案;例如只向右/下时,dp[r][c]=cell(r,c) ⊕ Aggregate(dp[r-1][c],dp[r][c-1])。遍历顺序必须拓扑兼容。

识别信号

容易误判的相似信号

SignalWhy it is different
允许四向任意循环普通表格顺序不再是拓扑序;最短路用 BFS/Dijkstra,计数需其他结构。
只问连通可达无需聚合路径价值时,DFS/BFS 更自然。
路径瓶颈目标若可四向且代价为路径最大值,可能是 minimax Dijkstra 或答案二分。

核心不变量

处理 (r,c) 时,它依赖的所有邻格状态已符合定义;写入后 dp[r][c] 汇总了所有合法进入方式且无遗漏重复。

状态、转移与处理顺序

ItemDefinition
State坐标 (r,c) 的最优值/计数;障碍格用不可达 sentinel。
Transition从所有合法前驱取 min/max/sum,再结合当前格贡献;起点独立初始化。
Frontier / order与移动方向一致的行列拓扑序;若只依赖上一行和当前行左侧,可压成一维。

Python 骨架

def min_grid_cost(grid):
    if not grid or not grid[0]: return 0
    rows, cols = len(grid), len(grid[0])
    dp = [float('inf')] * cols
    dp[0] = 0
    for r in range(rows):
        for c in range(cols):
            from_up = dp[c]
            from_left = dp[c - 1] if c else float('inf')
            if r == 0 and c == 0:
                dp[c] = grid[r][c]
            else:
                dp[c] = grid[r][c] + min(from_up, from_left)
    return dp[-1]

正确性思路

  1. 起点状态按唯一路径正确初始化。
  2. 拓扑顺序保证上方与左方已是正确子答案。
  3. 任一路径进入当前格的最后一步必来自一个合法前驱,取最优并加当前代价既完备又不漏;归纳到终点。

复杂度

TimeSpaceParameters
O(RC)O(C) 压缩;完整表 O(RC)R/C 为行列数;依赖半径更大时空间相应增加。

边界条件

错误模式

PatternWhy it fails / fix
遍历方向与依赖相反读取到本轮未计算或已覆盖状态;先画依赖箭头。
首行首列到处特判sentinel 或额外边界可统一转移,减少分支。
把循环网格当 DAG四向移动产生环时,单次扫描无法保证状态最终。
一维压缩覆盖上方值更新前明确 dp[c] 是旧行,dp[c-1] 是新行。

选择与排除规则

相关模板

RelationTemplateBoundary
相邻但非替代网格 Flood Fill方向形成 DAG 且要求计数或优化。
dimensional-extension线性 DP / 一维状态递推二维拓扑状态是线性 DP 的网格化。

原创微型例子

环节内容
Result最小代价路径经过左下,总成本 6。
Setup代价网格 [[2,5],[1,3]],只向右或下。
Trace到左下为 3,到右上为 7;右下取 min(3,7)+3=6。

Recall prompts

我的补充