63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 63. 不同路径 II - 图1 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? 网格中的障碍物和空位置分别用 10 来表示。 说明:mn 的值均不超过 100。 示例 1:

  1. 输入:
  2. [
  3. [0,0,0],
  4. [0,1,0],
  5. [0,0,0]
  6. ]
  7. 输出: 2
  8. 解释:
  9. 3x3 网格的正中间有一个障碍物。
  10. 从左上角到右下角一共有 2 条不同的路径:
  11. 1. 向右 -> 向右 -> 向下 -> 向下
  12. 2. 向下 -> 向下 -> 向右 -> 向右

解题思路

参考 简单DP,🤷‍♀️必须秒懂!

动态规划题。可以在【 62. 不同路径 】的二维dp实现方式上稍加改造。
同样时在二维数组中自顶向下的递推思路,且有核心状态转移方程 63. 不同路径 II - 图2
不同的是本题的网格中有障碍物,障碍是不可到达的,因此若 63. 不同路径 II - 图3为障碍物,63. 不同路径 II - 图4
不管是初始时或者在递归计算过程中,只要当前格子为障碍物,不可达,则 63. 不同路径 II - 图5
1、状态定义
63. 不同路径 II - 图6 表示走到格子63. 不同路径 II - 图7的方法数。

2、状态转移
如果网格 63. 不同路径 II - 图8 上有障碍物,则 63. 不同路径 II - 图9 值为 0,表示走到该格子的方法数为 0;
否则网格 63. 不同路径 II - 图10 可以从网格 63. 不同路径 II - 图11 或者 网格 63. 不同路径 II - 图12 走过来,因此走到该格子的方法数为走到网格 63. 不同路径 II - 图13 和网格 63. 不同路径 II - 图14 的方法数之和,即 63. 不同路径 II - 图15
状态转移方程如下:
63. 不同路径 II - 图16

3、初始条件
第 1 列的格子只有从其上边格子走过去这一种走法,因此初始化 dp [ i ] [ 0 ] 值为 1,存在障碍物时为 0;
第 1 行的格子只有从其左边格子走过去这一种走法,因此初始化 dp [ 0 ] [ j ] 值为 1,存在障碍物时为 0。

int dp[N][N] = {0};
//第一列初始化为 1 ,有障碍物则为0,且当前面有障碍物,直接退出,后面都为0
for(int i=0;i<n && obstacleGrid[i][0] == 0;i++) {
    dp[i][0] = 1;
}
//第一行初始化为 1,有障碍物则为0,且当前面有障碍物,直接退出,后面都为0
for(int i=0;i<m && obstacleGrid[0][i] == 0;i++) {
    dp[0][i] = 1;
}

完整代码实现

#define N 110
class Solution {
public:
   int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int n = obstacleGrid.size();
        if( n == 0 ) return 0;
        int m = obstacleGrid[0].size();
        //dp[i][j] 表示终点为(i,j)时的不同路径个数
        int dp[N][N] = {0};
        //第一列初始化为 1 ,有障碍物则为0,且当前面有障碍物,直接退出,后面都为0
        for(int i=0;i<n && obstacleGrid[i][0] == 0;i++) {
            dp[i][0] = 1;
        }
        //第一行初始化为 1,有障碍物则为0,且当前面有障碍物,直接退出,后面都为0
        for(int i=0;i<m && obstacleGrid[0][i] == 0;i++) {
            dp[0][i] = 1;
        }
        //从左至右从上至下遍历网格,填充dp
        for(int i=1;i<n;i++) {
          for(int j=1;j<m;j++) {
            dp[i][j] = obstacleGrid[i][j] == 0 ? (dp[i][j-1] + dp[i-1][j]):0;
          }
        }
        return dp[n-1][m-1];
    }
};