图解题库 / 二维 DP

64. 最小路径和

中等 含交互动画

学完这道你应该能: 说清它为什么用「二维 DP」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

网格每格是非负代价,只能右/下走,求左上到右下路径上代价之和的最小值

网格 = 1 3 1 / 1 5 1 / 4 2 1
输出 = 7 (1→3→1→1→1)

思路解析

一个格子只能从上或左来,那咱当然挑代价小的那条接上:dp[i][j] = min(上, 左) + grid[i][j]。第一行和第一列只有一条路,前缀累加就行。

第一行/列 · 累加:第一行只能一路向右:1、1+3=4、4+1=5;第一列只能向下:1、1+1=2、2+4=6。都是前缀和。

填 (1,1):(1,1) 代价 5,从上(4)或左(2)来,挑小的 2:dp = 2 + 5 = 7。

填 (1,2):(1,2) 代价 1,min(上5, 左7)=5,dp = 5 + 1 = 6。

填 (2,1):(2,1) 代价 2,min(上7, 左6)=6,dp = 6 + 2 = 8。

右下角:右下角 = min(上6, 左8) + 1 = 7,就是最小路径和。

同一张网格 DP 表,换聚合方式就解不同题:计数用加法、求最小用 min、求最大用 max。

参考代码(Python)

Python
1dp = [[0]*n for _ in range(m)]
2dp[0][0] = grid[0][0]
3for j in range(1, n): dp[0][j] = dp[0][j-1] + grid[0][j]   # 第一行
4for i in range(1, m): dp[i][0] = dp[i-1][0] + grid[i][0]   # 第一列
5for i in range(1, m):
6    for j in range(1, n):
7        dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
8return dp[m-1][n-1]

复杂度分析

  • 时间复杂度:O(m×n) —— 每格算一次
  • 空间复杂度:O(m×n) —— 可压成一行

套路模板

记住骨架:边界前缀累加、中间 min(上,左)+当前。求最大路径和就把 min 换 max,三角形最小路径和也是它。

Python
1dp[0][0] = grid[0][0]
2# 第一行/列前缀累加
3for i in range(1, m):
4    for j in range(1, n):
5        dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
6return dp[m-1][n-1]

易错点

  • 第一行/列也用 min 公式 → ✅ 第一行/列单独前缀累加(它们没有「上」或「左」,硬套会取到不存在的格)
  • 忘了加当前格代价 → ✅ min(上,左) 之后要 + grid[i][j](路径和要算上当前格)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →213. 打家劫舍 II ← 返回题库