本文共 2380 字,大约阅读时间需要 7 分钟。
在一个M×N网格中,有一个机器人从左上角的“Start”位置移动到右下角的“Finish”位置。机器人每次只能向下或向右移动一步。我们需要计算有多少条不同的路径。
这个问题属于经典的组合数学问题,可以通过动态规划(DP)来解决。动态规划是一种高效的算法方法,能够将大型问题分解为更小的子问题,从而逐步求解。
我们使用一个二维数组 dp
来存储每个位置的路径数。dp[i][j]
表示从左上角到位置 (i, j) 的路径数。
边界条件:
dp[0][j] = 1
对于所有 jdp[i][0] = 1
对于所有 i递推公式:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
优化空间复杂度:
dp
代替二维数组,可以将空间复杂度从 O(MN) 降低到 O(N)。int uniquePaths(int m, int n) { vector dp(n, 1); for (int i = 1; i < m; ++i) { for (int j = 1; j < n; ++j) { dp[j] += dp[j - 1]; } } return dp.back();}
dp
,长度为 n,所有元素初始化为 1。dp[j]
为 dp[j] + dp[j-1]
,即左边位置的路径数加上上边位置的路径数。dp.back()
。以 3×7 网格为例:
为了进一步验证,我们引入障碍物,将网格中的某些位置标记为无法通过。
给定一个 M×N 的网格,网格中包含障碍物和空位。障碍物用 1 表示,空位用 0 表示。计算从起点到终点的路径数,排除经过障碍物的路径。
dp
:同样用于存储当前位置的路径数。if (obstacleGrid[i-1][j] == 1 || obstacleGrid[i][j-1] == 1) { dp[i][j] = 0;} else { dp[i][j] = (dp[i-1][j] + dp[i][j-1]);}
考虑一个 3×3 网格:
[\begin{bmatrix}0 & 0 & 0 \0 & 1 & 0 \0 & 0 & 0\end{bmatrix}]
代码输出 2,即存在两条有效路径。
int uniquePathsWithObstacles(vector> obstacleGrid) { int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); vector dp(m, vector (n, 0)); dp[0][0] = 1; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (i == 0 && j == 0) continue; if (obstacleGrid[i][j] == 1) { dp[i][j] = 0; continue; } int ways = 0; if (i > 0 && obstacleGrid[i-1][j] != 1 && dp[i-1][j] > 0) { ways += dp[i-1][j]; } if (j > 0 && obstacleGrid[i][j-1] != 1 && dp[i][j-1] > 0) { ways += dp[i][j-1]; } dp[i][j] = ways; } } return dp.back().back();}
dp
数组,起点为 1。dp[m-1][n-1]
即终点位置的路径数。通过上述方法,我们可以在 O(MN) 时间复杂度内解决问题。动态规划是一种强大的工具,能够帮助我们解决路径计数问题,扩展性良好,可以轻松处理有障碍物的情况。
如果将网格尺寸进一步扩大,可以考虑使用 memoization 或递归方法,以优化代码的可读性。
转载地址:http://dywfk.baihongyu.com/