一、题目解析
这道题和上一道题的区别在于,这道题是有障碍物的,如果路径上有障碍物,那你是不能走的,1表示障碍物。 相信大家看完题目是都能看懂的,因此我们直接来做一下这道题。
二、算法原理
1、状态表示:
根据我们上一道题的经验,再加上题目要求,我们可以直接先定义一个状态表示,如果推不出状态转移方程我们在去修改它。
dp[i][j]表示:到达[i][j]位置共多少条路径。
2、状态转移方程:
根据题目要求我们只能从[i-1][j]和[i][j-1]这两个位置到达[i][j]位置,因此我们如果知道到达[i-1][j]和[i][j-1]有多少条路径,那么在每一种路径后面再加上一步就可以到达[i][j]位置,这两个位置的路径个数在哪里呢?不就在dp[i-1][j]和dp[i][j-1]里面吗?但是,此时我们还要考虑一个问题,这道题路径上是有障碍物的呀,如果[i][j]这个位置上是障碍物你能到达吗?你肯定不能到达呀,因此我们仅需要判断一下[i][j]位置上有没有障碍物即可。
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。这里我给它换个颜色,因为是需要判断的。如果这个位置上是障碍物,直接就是0。
3、初始化:
同样的,我们填[i][j]状态的时候是需要上面一个状态和左面一个状态的,因此我们可以采取多加一行多加一列的方式。其次我们还有考虑一下起点位置初始化为什么,起点位置的值应该是几呢?是不是应该是1呀,你只能从自己到自己。因此左面或者上面的位置初始化为1即可。
4、填表:
因为初始化的时候多加了一行多加了一列,因此我们在判断当前位置有没有障碍物的时候一定要注意下标的映射关系。填表顺序大方向从上往下,每一行从左往右即可
5、返回值:
因为初始化的时候多加了一行多加了一列,因此我们在返回结果的时候返回dp[m][n]即可。
在这里给大家说一点,就是我们做题的时候一定不要吝啬你的纸和笔,该画图的时候就画图。
三、编写代码
希望大家可以自己根据算法原理尝试编写一下代码。
class Solution
{
public:
int uniquePathsWithObstacles(vector<vector<int>>& nums)
{
int m = nums.size(), n = nums[0].size();
//1、创建dp表
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
//2、初始化
dp[1][0] = 1;
//3、填表
for(int i = 1; i <= m; i++)
{
for(int j = 1; j <= n; j++)
{
//一定要注意下标的映射关系
if(nums[i - 1][j - 1] == 0) dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
//4、返回结果
return dp[m][n];
}
};