题目描述
网格里 1 是障碍,只能右/下走,求从左上到右下的路径数。
网格 = 0 0 0 / 0 1 0 / 0 0 0
输出 = 2
思路解析
正常格子 dp[i][j] = 上 + 左;遇到障碍,这格谁也到不了,dp 直接置 0,它也就不会再把走法数传给右边和下边。
第一行/列:第一行、第一列没有障碍挡路,照常填 1(只有一条直路)。
障碍格 (1,1) = 0:(1,1) 是障碍,dp 直接记 0——没有任何走法能停在障碍上。
填 (1,2):(1,2) = 上面 1 + 左边 0(障碍传来的)= 1。障碍的「0」自动让这条路少了。
填 (2,1):(2,1) = 上面 0(障碍)+ 左边 1 = 1。
右下角:右下角 = 上 1 + 左 1 = 2,正是绕过障碍的 2 条路。
网格 DP 里遇到「不可用的格子」,把它的 dp 置 0 或无穷,它就不会再向后传递——障碍、陷阱、禁区都这么处理。
参考代码(Python)
Python
1if grid[0][0] == 1: return 0
2dp = [[0]*n for _ in range(m)]
3dp[0][0] = 1
4for i in range(m):
5 for j in range(n):
6 if grid[i][j] == 1: dp[i][j] = 0; continue # 障碍
7 if i: dp[i][j] += dp[i-1][j] # 上
8 if j: dp[i][j] += dp[i][j-1] # 左
9return dp[m-1][n-1]复杂度分析
- 时间复杂度:O(m×n) —— 每格算一次
- 空间复杂度:O(m×n) —— 可压成一行
套路模板
记住骨架:障碍格清零跳过、其余「上+左」累加。把「相加」换成 min/max,就能解带障碍的最小路径和等题。
Python
1dp = [[0]*n for _ in range(m)]; dp[0][0] = 1
2for i in range(m):
3 for j in range(n):
4 if 不可用(i, j): dp[i][j] = 0; continue # 障碍清零
5 if i: dp[i][j] += dp[i-1][j]
6 if j: dp[i][j] += dp[i][j-1]
7return dp[m-1][n-1]易错点
- ❌ 起点/终点就是障碍没处理 → ✅ 先判 grid[0][0]==1 返回 0(起点被堵则一条路都没有)
- ❌ 障碍格还去算上+左 → ✅ 障碍格直接 0 并 continue(否则会把不存在的路径数传下去)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。