力扣-动态规划-63. 不同路径 II
63. 不同路径 II
题目描述
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
- 向右 -> 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右 -> 向右
示例 2:
输入:obstacleGrid = [[0,1],[0,0]]
输出:1
提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:动态规划
今天接着刷第四道动态规划的题目,在正式开始做题之前我们来复习一下动态规划的思路,动态规划思路:
1. 确定dp数组及下标的含义,本题要求的是路径的数量,并且是m*n的表格,那么dp(m,n)就代表从起点到(m,n)位置路径的数量。
2. 确定状态转移方程,也就是递推公式。动态规划的特点是前面的决策会影响到后面的决策,也就是前面不同的决策会影响后面的结果。本题中到达终点只有两个方向,从终点的上方或者左方,再结合举例推导得到的规律,可以推出递推公式为:dp(m,n) = dp(m - 1,n) + dp(m,n - 1);
3. dp数组初始化,本题和62. 不同路径的区别在于会有障碍物,就需要考虑到障碍物的dp。有(m,n)位置有障碍物时,从起点肯定到不了该位置,因此dp(m,n)一定为0。
4. 遍历顺序,在没有障碍物情况下dp第一行所有列已经初始化为1,第一列也全部初始化为1。如果在第一行或者第一列存在障碍物,则障碍物位置和障碍物位置以后的dp都为0。在遍历过程中,有障碍物位置的dp也为0。结合表格图可以知道当前位置的路径数量是有同一行的上一列和同一列的上一行dp值相加得到,因此遍历顺序是每一行依次从左到右。
5. 举例推导dp,与代码结果比较。
本题和上一道题目核心内容都是一样的,区别就是增加了障碍物位置dp为0的判断。
我自己写的代码如下,代码已经加了注释,各位小伙伴如果有什么问题可以在评论里提出来,欢迎大家交流。
//动态规划 前面的状态会影响到后面的决策
//动态规划
//1.dp[m,n]代表从起点到达(m,n)位置的路径数量
//2.状态转移方程 dp[m,n] = dp[m - 1, n] + dp[m, n - 1];
//3.初始化 (m,n)位置没有障碍物时,m=1或者n=1时dp[m,n]=1;(m,n)位置有障碍物时,dp[m,n]=0;
//4.遍历顺序 一行一行从左到右遍历
//5.举例推导
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
//对第一行初始化
for (int i = 0; i < m; i++) {
if (obstacleGrid[i][0] == 1) {//出现障碍物 后面位置dp都为0
break;
} else {
dp[i][0] = 1;
}
//System.out.println("dp[" + i + "][0]: " + dp[i][0]);
}
//对第一列初始化
for (int i = 0; i < n; i++) {
if (obstacleGrid[0][i] == 1) {//有障碍物 后面位置dp都为0
break;
} else {
dp[0][i] = 1;
}
//System.out.println("dp[0][" + i + "]: " + dp[0][i]);
}
//递归
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (obstacleGrid[i][j] != 1) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
} else {
continue;
}
//System.out.println("dp[" + i + "][" + j + "]: " + dp[i][j]);
}
}
return dp[m - 1][n - 1];
}
另外附上我自己搭建的个人博客网址,里面记录了我之前记录的学习心得,欢迎大家交流讨论。