63.不同路径二
力扣链接:63. 不同路径 II - 力扣(Leetcode)
题目
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
思路
首先此题是62. 不同路径 - 力扣(Leetcode)的进阶,只多了一个限制条件,图中障碍处不能通过。
此题的方法依旧是动态规划。
dp[i][j]
表示从左上角到第i行j列元素的不同的路径总数
根据题意,第i行j列的位置可以由第i-1行j列的位置向下一步得到,也可以由第i行j-1列的位置向右得到。因此,dp[i][j]
=dp[i-1][j]
+dp[i][j-1]
。
但是考虑到题目中的障碍物,倘若[i-1][j]
的位置恰好是障碍物,那么[i][j]
只有可能是由[i][j-1]
向右一步得到,因为[i-1][j]
处为障碍物,无法通过;同理倘若[i][j-1]
为障碍物,dp[i][j]=dp[i-1][j]
;倘若[i-1][j],[i][j-1]
都为障碍物,那么dp[i][j]
=0;
整理以上,得出状态转移方程:用map代表地图
-
map
[i-1][j]
==0 , dp[i][j]
=dp[i][j-1]
-
map
[i][j-1]
==0 , dp[i][j]
=dp[i-1][j]
-
map
[i-1][j]
==0 map[i][j-1]
==0, dp[i][j]
=0 -
map
[i-1][j]
!=0 map[i][j-1]
!=0, dp[i][j]
==dp[i-1][j]
+dp[i][j-1]
如何初始化dp二维数组?
dp[0][i]
或是dp[i][0]
都只能由上一步向下,或者向右得到。即[0][1]
只能由[0][0]
向右一步得到,倘若没有障碍物,全部都应该是1。
但是假设第一行或者第一列中某个元素是障碍物,那么在此之后的所有元素都无法通过。即假设[0][5]
是障碍物,那么[0][6]...[0][n]
都被卡在[0][5]
处,障碍物无法穿越,也就是[0][6]...[0][n]
都为0。
伪代码:
对于第一行:if(map[0][i]
==1) break; else dp[0][i]=1
对于第一列:if(map[i][0]
==1) break; else dp[i][0]=1
代码
class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { /* dp[i][j]表示从左上角到第i行j列的位置的总路径数 */ int row = obstacleGrid.length; int col = obstacleGrid[0].length; int[][] dp = new int[row][col]; for (int i = 0; i < row; i++) { if(obstacleGrid[i][0] == 1){ dp[i][0] = 0; break; } else { dp[i][0] = 1; } } for (int i = 0; i < col; i++) { if(obstacleGrid[0][i] == 1) { dp[0][i] = 0; break; } else { dp[0][i] = 1; } } for (int i = 1; i < row; i++) { for (int j = 1; j < col; j++) { if(obstacleGrid[i][j] == 1) { dp[i][j] = 0; } else { if (obstacleGrid[i - 1][j] == 1) { dp[i][j] = dp[i][j - 1]; } else if (obstacleGrid[i][j - 1] == 1) { dp[i][j] = dp[i - 1][j]; } else { dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } } } } return dp[row-1][col-1]; } }