引言
在动态规划的进阶学习中,二维数组是常见的状态空间。与一维 DP 相比,二维 DP 的状态表示从单点扩展到了平面上的坐标 (i, j),管理的维度也随之增加。处理这类问题时,核心依然遵循'五步法':状态定义、状态转移方程、初始化、遍历顺序、返回值。
对于二维网格问题,通常建议采用'虚拟行/列'的技巧来简化边界判断,避免复杂的 if-else 嵌套。下面通过五个经典案例,由浅入深地梳理二维路径问题的解题思路。
1. 不同路径
题目描述: 一个机器人位于一个 m x n 网格的左上角,每次只能向下或者向右移动一步。问总共有多少条不同的路径到达右下角?
思路分析: 这是一个最基础的二维 DP 模型。
- 状态定义:
dp[i][j]表示从起点到达位置(i, j)的路径总数。 - 转移方程:要到达
(i, j),只能从上方(i-1, j)或左方(i, j-1)过来。因此dp[i][j] = dp[i-1][j] + dp[i][j-1]。 - 初始化:为了避免处理第一行和第一列的越界判断,我们可以将
dp数组多开一行和一列(大小为(m+1) x (n+1))。将dp[0][1]设为 1,这样在计算第一行和第一列时,逻辑上会自动累加为 1,无需特殊处理边界。 - 遍历顺序:从上到下,从左到右。
- 返回值:
dp[m][n]。
代码实现:
class Solution {
public:
int uniquePaths(int m, int n) {
// 多开一行一列,用于处理边界,初始化为 0
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// 关键技巧:设置虚拟起点,使得第一行和第一列能自动推导为 1
dp[0][1] = 1;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
dp[i][j] = dp[i - 1][j] + dp[i][j - ];
}
}
dp[m][n];
}
};


