Skip to content

Commit b197dec

Browse files
committed
feat: add unique patsh with obstacle dynamic programing
1 parent a2024c8 commit b197dec

File tree

4 files changed

+131
-3
lines changed

4 files changed

+131
-3
lines changed
-15 KB
Binary file not shown.

leetcode/dynamic_programming/unique_paths.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class Solution
7575
* 根据递归公式 dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 可以看出,dp[i][j] 都是从其上方或者左方推导出来,
7676
* 所以从左到右一层一层遍历就可以了。这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。
7777
* 5. 举例推导dp数组
78-
* m = 3, n = 7
78+
* m = 3, n = 7
7979
* ├───────────────────────────│
8080
* │ 1 │ 1 │ 1 │ 1 │ 1 │ 1 │ 1 │
8181
* ├───────────────────────────│
@@ -97,9 +97,9 @@ int Solution::uniquePaths(int m, int n)
9797
for (int j = 0; j < n; j++)
9898
dp[0][j] = 1;
9999

100-
for (int i = 0; i < m; i++)
100+
for (int i = 1; i < m; i++)
101101
{
102-
for (int j = 0; j < n; j++)
102+
for (int j = 1; j < n; j++)
103103
{
104104
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
105105
}
52.2 KB
Binary file not shown.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* @Author: Chacha
3+
* @Date: 2022-03-05 13:40:09
4+
* @Last Modified by: Chacha
5+
* @Last Modified time: 2022-03-05 20:32:53
6+
*/
7+
8+
/**
9+
* 来源:https://leetcode-cn.com/problems/unique-paths-ii/
10+
*
11+
* 动态规划 - 不同路径II
12+
* 一个机器人位于一个 m x n (1 <= m, n <= 100) 网格的左上角 (起始点在下图中标记为 “Start” )。
13+
* 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
14+
* 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 1 和 0 来表示。
15+
*
16+
* 示例 1:
17+
* 输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
18+
* 输出:2
19+
*
20+
* ├─────────────────│
21+
* │ S │ 0 │ 0 │
22+
* ├─────────────────│
23+
* │ 0 │ 1 │ 0 │
24+
* ├─────────────────│
25+
* │ 0 │ 0 │ F │
26+
* ├─────────────────│
27+
*
28+
* 解释:3 x 3网格的正中间有一个障碍物。从左上角到右下角一共有2条不同的路径:
29+
* 1. 向右 -> 向右 -> 向下 -> 向下
30+
* 2. 向下 -> 向下 -> 向右 -> 向右
31+
*
32+
*/
33+
34+
#include <iostream>
35+
#include <vector>
36+
37+
using namespace std;
38+
39+
class Solution
40+
{
41+
public:
42+
int uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid);
43+
};
44+
45+
/**
46+
* 机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。
47+
* 按照动规五部曲来分析:
48+
* 1. 确定dp数组(dp table)以及下标的含义
49+
* dp[i][j]: 表示从(0, 0)出发,到(i, j) 有 dp[i][j] 条不同的路径
50+
* 2. 确定递推公式
51+
* 可以推导出公式:dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。因为有了障碍,所以当(i, j)没有障碍的时候,再推导dp[i][j]。
52+
* 所以代码为:
53+
* if (obstacleGrid[i][j] == 0) dp[i][j] = dp[i - 1][j] + dp[j][i - 1]
54+
* 3. dp数组初始化
55+
* 首先dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。
56+
* 但如果(i, 0)这条边又了障碍之后,障碍之后都是走不到的位置,所以障碍之后的dp[i][0]应该还是初始值0。
57+
* ├─────────────────────────────────────────│
58+
* │ 1 │ 1 │ 1 │ 障碍 │ 0 │ 0 │ 0 │
59+
* ├─────────────────────────────────────────│
60+
* 所以初始化代码为:
61+
* for(int i = 0, i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
62+
* for(int j = 0, j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
63+
* 4. 确定遍历顺序
64+
* 根据递归公式 dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 可以看出,dp[i][j] 都是从其上方或者左方推导出来,
65+
* 所以从左到右一层一层遍历就可以了。这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。
66+
* 代码如下:
67+
* for (int i = 1; i < m; i++) {
68+
* for (int j = 1; j < n; j++) {
69+
* if (obstacleGrid[i][j] == 1) continue;
70+
* dp[i][j] = dp[i - 1][j] + dp[i][j-1]
71+
* }
72+
* }
73+
*
74+
* 5. 举例推导dp数组
75+
* obstacleGrid = [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
76+
* ├─────────────────│
77+
* │ S │ 1 │ 1 │
78+
* ├─────────────────│
79+
* │ 1 │ 0 │ 1 │
80+
* ├─────────────────│
81+
* │ 1 │ 1 │ F │
82+
* ├─────────────────│
83+
*
84+
* 时间复杂度: O(m × n)
85+
* 空间复杂度: O(m x n)
86+
*
87+
*/
88+
int Solution::uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid)
89+
{
90+
int m = obstacleGrid.size();
91+
int n = obstacleGrid[0].size();
92+
93+
vector<vector<int>> dp(m, vector<int>(n, 0));
94+
95+
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++)
96+
dp[i][0] = 1;
97+
98+
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++)
99+
dp[0][j] = 1;
100+
101+
for (int i = 1; i < m; i++)
102+
{
103+
for (int j = 1; j < n; j++)
104+
{
105+
if (obstacleGrid[i][j] == 1)
106+
continue;
107+
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
108+
}
109+
}
110+
111+
return dp[m - 1][n - 1];
112+
};
113+
114+
int main(int argc, char const *argv[])
115+
{
116+
Solution s;
117+
118+
vector<vector<int>> obstacleGrid(3, vector<int>(3, 0));
119+
vector<vector<int>> obstacleGrid1(2, vector<int>(2, 0));
120+
121+
obstacleGrid[1][1] = 1;
122+
obstacleGrid1[0][1] = 1;
123+
124+
cout << "Result is: " << s.uniquePathsWithObstacles(obstacleGrid) << endl;
125+
cout << "Result is: " << s.uniquePathsWithObstacles(obstacleGrid1) << endl;
126+
127+
return 0;
128+
}

0 commit comments

Comments
 (0)