63. 不同路径 II
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? 网格中的障碍物和空位置分别用
1和0来表示。 说明:m 和 n 的值均不超过 100。 示例 1:
输入:[[0,0,0],[0,1,0],[0,0,0]]输出: 2解释:3x3 网格的正中间有一个障碍物。从左上角到右下角一共有 2 条不同的路径:1. 向右 -> 向右 -> 向下 -> 向下2. 向下 -> 向下 -> 向右 -> 向右
解题思路
动态规划题。可以在【 62. 不同路径 】的二维dp实现方式上稍加改造。
同样时在二维数组中自顶向下的递推思路,且有核心状态转移方程
不同的是本题的网格中有障碍物,障碍是不可到达的,因此若 为障碍物,
不管是初始时或者在递归计算过程中,只要当前格子为障碍物,不可达,则
1、状态定义: 表示走到格子
的方法数。
2、状态转移:
如果网格 上有障碍物,则
值为 0,表示走到该格子的方法数为 0;
否则网格 可以从网格
或者 网格
走过来,因此走到该格子的方法数为走到网格
和网格
的方法数之和,即
状态转移方程如下:
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];
}
};
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 