A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

Note: m and n will be at most 100.

Example 1:

Input:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right

这道题是之前那道 Unique Paths 的延伸,在路径中加了一些障碍物,还是用动态规划 Dynamic Programming 来解,使用一个二维的 dp 数组,大小为 (m+1) x (n+1),这里的 dp[i][j] 表示到达 (i-1, j-1) 位置的不同路径的数量,那么i和j需要更新的范围就是 [1, m] 和 [1, n]。状态转移方程跟之前那道题是一样的,因为每个位置只能由其上面和左面的位置移动而来,所以也是由其上面和左边的 dp 值相加来更新当前的 dp 值,如下所示:

dp[i][j] = dp[i-1][j] + dp[i][j-1]

这里就能看出来初始化 d p数组的大小为 (m+1) x (n+1),是为了 handle 边缘情况,当i或j为0时,减1可能会出错。当某个位置是障碍物时,其 dp 值为0,直接跳过该位置即可。这里还需要初始化 dp 数组的某个值,使得其能正常累加。当起点不是障碍物时,其 dp 值应该为1,即dp[1][1] = 1,由于其是由 dp[0][1] + dp[1][0] 更新而来,所以二者中任意一个初始化为1即可。由于之后 LeetCode 更新了这道题的 test case,使得使用 int 型的 dp 数组会有溢出的错误,所以改为使用 long 型的数组来避免 overflow,代码如下:

解法一:

class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
if (obstacleGrid.empty() || obstacleGrid[].empty() || obstacleGrid[][] == ) return ;
int m = obstacleGrid.size(), n = obstacleGrid[].size();
vector<vector<long>> dp(m + , vector<long>(n + , ));
dp[][] = ;
for (int i = ; i <= m; ++i) {
for (int j = ; j <= n; ++j) {
if (obstacleGrid[i - ][j - ] != ) continue;
dp[i][j] = dp[i - ][j] + dp[i][j - ];
}
}
return dp[m][n];
}
};

或者我们也可以使用一维 dp 数组来解,省一些空间,参见代码如下:

解法二:

class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
if (obstacleGrid.empty() || obstacleGrid[].empty() || obstacleGrid[][] == ) return ;
int m = obstacleGrid.size(), n = obstacleGrid[].size();
vector<long> dp(n, );
dp[] = ;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (obstacleGrid[i][j] == ) dp[j] = ;
else if (j > ) dp[j] += dp[j - ];
}
}
return dp[n - ];
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/63

类似题目:

Unique Paths

Unique Paths III

参考资料:

https://leetcode.com/problems/unique-paths-ii/

https://leetcode.com/problems/unique-paths-ii/discuss/23250/Short-JAVA-solution

https://leetcode.com/problems/unique-paths-ii/discuss/23248/My-C%2B%2B-Dp-solution-very-simple!

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Unique Paths II 不同的路径之二的更多相关文章

  1. [LeetCode] 63. Unique Paths II 不同的路径之二

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  2. LEETCODE —— Unique Paths II [动态规划 Dynamic Programming]

    唯一路径问题II Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are ...

  3. LeetCode: Unique Paths II 解题报告

    Unique Paths II Total Accepted: 31019 Total Submissions: 110866My Submissions Question Solution  Fol ...

  4. LEETCODE —— Unique Paths II [Dynamic Programming]

    唯一路径问题II Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are ...

  5. LeetCode OJ:Unique Paths II(唯一路径II)

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  6. [Leetcode] unique paths ii 独特路径

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  7. [leetcode]Unique Paths II @ Python

    原题地址:https://oj.leetcode.com/problems/unique-paths-ii/ 题意: Follow up for "Unique Paths": N ...

  8. Leetcode Unique Paths II

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  9. Leetcode之动态规划(DP)专题-63. 不同路径 II(Unique Paths II)

    Leetcode之动态规划(DP)专题-63. 不同路径 II(Unique Paths II) 初级题目:Leetcode之动态规划(DP)专题-62. 不同路径(Unique Paths) 一个机 ...

随机推荐

  1. [转] 给ubuntu中的软件设置desktop快捷方式(以android studio为例)

    原文链接:http://www.cnblogs.com/kinyoung/p/4493472.html ubuntu的快捷方式都在/usr/share/applications/路径下有很多*.des ...

  2. ubuntu安装navicat及常见问题解决

    1.安装navicat Step1: 下载Navicat ,网址:http://www.navicat.com/en/download/download.html Step2:进入下载目录,解压压缩包 ...

  3. C++_系列自学课程_第_11_课_类型转换_《C++ Primer 第四版》

    上次说了关于表达式的一些内容,说到还有一些关于数据类型转换的内容,今天我们接着八一八C++中的数据类型转换. 一.隐式类型转换 在表达式中,有些操作符可以对多种类型的操作数进行操作, 例如 + 操作符 ...

  4. 一些简单的C语言算法

    1. 要求输入一个正整数,打印下述图形 输入:5 输出: * ** *** **** ***** 实现代码如下: #include <stdio.h> int main(int argc, ...

  5. 计算(LnN!)的值

    import java.util.*;import java.math.*;public class CaculatorLnN { public static void main(String[] a ...

  6. FastDFS 安装及使用

    FastDFS 安装及使用 2012-11-17 13:10:31|  分类: Linux|举报|字号 订阅     Google了一下,流行的开源分布式文件系统有很多,介绍如下:   mogileF ...

  7. nginx+lua

    一场电闪与雷鸣的结合, 公司原有服务器已经配置好nginx,需要重新装载lua模块,哈哈哈,无法无法.   安装LUA模块需要以下 pcre       ftp://ftp.csx.cam.ac.uk ...

  8. Java程序员应该掌握的10项技能

    这篇文章主要介绍了作为Java程序员应该掌握的10项技能,包括java的知识点与相关的技能,对于java的学习有不错的参考借鉴价值,需要的朋友可以参考下   1.语法:必须比较熟悉,在写代码的时候ID ...

  9. Hibernate入门详解

    学习Hibernate ,我们首先要知道为什么要学习它?它有什么好处?也就是我们为什么要学习框架技术? 还要知道    什么是Hibernate?    为什么要使用Hibernate?    Hib ...

  10. opts=opts | |{}

    var opts=opts || {}这个语句是一个赋值或者初始化语句 该语句在opts已经被初始化过后opts的值不变,即执行var opts=opts这一部分. 当opts未被初始化,即typeo ...