6.不同路径Ⅱ(medium)

1.题目链接:

63. 不同路径 II - 力扣(LeetCode)63. 不同路径 II - 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0])。机器人尝试移动到 右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。返回机器人能够到达右下角的不同路径数量。测试用例保证答案小于等于 2 * 109。 示例 1:[https://assets.leetcode.com/uploads/2020/11/04/robot1.jpg]输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]输出:2解释:3x3 网格的正中间有一个障碍物。从左上角到右下角一共有 2 条不同的路径:1. 向右 -> 向右 -> 向下 -> 向下2. 向下 -> 向下 -> 向右 -> 向右示例 2:[https://assets.leetcode.com/uploads/2020/11/04/robot2.jpg]输入:obstacleGrid = [[0,1],[0,0]]输出:1 提示: * m == obstacleGrid.length * n == obstacleGrid[i].length * 1 <= m, n <= 100 * obstacleGrid[i][j] 为 0 或 1https://leetcode.cn/problems/unique-paths-ii/description/

2.题目描述:

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。​机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。​
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。​

示例 1:​

     输入:
               obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]​
     输出:
               2​
     解释:
               3x3 网格的正中间有一个障碍物。​
               从左上角到右下角一共有 2 条不同的路径:​
              a. 向右 -> 向右 -> 向下 -> 向下​
              b. 向下 -> 向下 -> 向右 -> 向右​
3. 解法(动态规划):
算法思路:
本题为不同路径的变型,只不过有些地方有「障碍物」,只要在「状态转移」上稍加修改就可解决。

1. 状态表示:
        对于这种「路径类」的问题,我们的状态表示一般有两种形式:

i.

[i, j]  位置出发,巴拉巴拉;​

  ii. 从起始位置出发,到达 [i, j]  位置,巴拉巴拉。​这里选择第二种定义状态表示的方式:
dp[i][j]  表示:走到 [i, j]  位置处,一共有多少种方式。​

2. 状态转移:
简单分析一下。如果 dp[i][j]  表示到达 [i, j]  位置的方法数,那么到达 [i, j]  位置之前的一小步,有两种情况:

i.

[i, j]  位置的上方([i - 1, j]  的位置)向下走一步,转移到 [i, j]  位置;​

ii.[i, j]  位置的左方([i, j - 1]  的位置)向右走一步,转移到 [i, j]  位置。​

但是,[i - 1, j]  与 [i, j - 1]  位置都是可能有障碍的,此时从上面或者左边是不可能

到达 [i, j]  位置的,也就是说,此时的方法数应该是 0。​

由此我们可以得出一个结论,只要这个位置上「有障碍物」,那么我们就不需要计算这个位置上的

值,直接让它等于 0  即可。​

3. 初始化:

可以在最前面加上一个「辅助结点」,帮助我们初始化。使用这种技巧要注意两个点:

i.     辅助结点里面的值要「保证后续填表是正确的」;

ii. 「下标的映射关系」。

在本题中,添加一行,并且添加一列后,只需将 dp[1][0]  的位置初始化为 1  即可。​

4. 填表顺序:

根据「状态转移」的推导,填表的顺序就是「从上往下」填每一行,每一行「从左往右」。

5. 返回值:

根据「状态表示」,我们要返回的结果是 dp[m][n] 。​

Java算法代码:

class Solution {
    public int uniquePathsWithObstacles(int[][] ob) {
        //1.创建dp表
        //2.初始化
        // 3.填表
        // 4.返回
        int m = ob.length, n = ob[0].length;
        int [][] dp = new int[m+1][n+1];
        dp[1][0] = 1;
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <=n; j++){
                if(ob[i - 1][j - 1] == 0){
                    dp[i][j] = dp[i -1][j] + dp[i][j-1];
                }
            }
        }
        return dp[m][n];
    }
}

运行结果:

动态规划:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值