1543 · Unique Path IV
Algorithms
Description
Solution14
Notes
Discuss26
Leaderboard
Record
Description
Give two integers to represent the height and width of the grid. The starting point is in the upper left corner and the ending point is in the upper right corner. You can go to the upper right corner, right or lower right corner. Find out the number of paths you can reach the end. And the result needs to mod 1000000007.
width > 1, height > 1
Example
Example 1:
Input:
height = 3
width = 3
Output:
2
Explanation: There are two ways from start to end.
image
Example 2:
Input:
height = 2
weight = 2
Output:
1
Explanation: There are only one way from (1,1) to (2,1)
解法1:
反过来逆推,从右上角开始,那么行要从上到下,列要从右到左。
注意:很重要的一点是列要放在外循环!
以5行4列矩阵为例,a[0][4]为终点,dp[0][4]=1。那么其相邻的dp[0][3]=1, dp[1,3]=1,dp[1][4]=0。
如果行循环在外面,那么列会先更新,dp[0][3]=1,dp[0][2]=1,…。我们可以看到dp[0][3]先于dp[1][4]更新,但实际上dp[0][3]应该后于dp[1][4]。
class Solution {
public:
/**
* @param height: the given height
* @param width: the given width
* @return: the number of paths you can reach the end
*/
int uniquePath(int height, int width) {
#define MOD 1000000007
if (height == 0 || width == 0) return 1;
vector<vector<int>> dp(height, vector<int>(width, 0));
dp[0][width - 1] = 1;
for (int j = width - 1; j >= 0; j--) { //注意列在先。因为
for (int i = 0; i < height; i++) {
if (j - 1 >= 0) {
if (i + 1 < height) {
dp[i + 1][j - 1] = (dp[i + 1][j - 1] + (dp[i][j] % MOD)) % MOD;
}
dp[i][j - 1] = (dp[i][j - 1] + (dp[i][j] % MOD)) % MOD;
if (i - 1 >= 0) {
dp[i - 1][j - 1] = (dp[i - 1][j - 1] + (dp[i][j] % MOD)) % MOD;
}
}
}
}
return dp[0][0] % MOD;
}
};
解法2:正向推。注意:很重要的一点也是列要放在外循环!
class Solution {
public:
/**
* @param height: the given height
* @param width: the given width
* @return: the number of paths you can reach the end
*/
int uniquePath(int height, int width) {
#define MOD 1000000007
if (height == 0 || width == 0) return 1;
vector<vector<int>> dp(height, vector<int>(width, 0));
dp[0][0] = 1;
for (int j = 0; j < width; j++) {
for (int i = 0; i < height; i++) {
if (j - 1 >= 0) {
dp[i][j] = (dp[i][j] + dp[i][j - 1]) % MOD;
if (i - 1 >= 0) {
dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % MOD;
}
if (i + 1 < height) {
dp[i][j] = (dp[i][j] + dp[i + 1][j - 1]) % MOD;
}
}
}
}
return dp[0][width - 1];
}
};
上面的if (j-1>=0)可以简化
class Solution {
public:
/**
* @param height: the given height
* @param width: the given width
* @return: the number of paths you can reach the end
*/
int uniquePath(int height, int width) {
#define MOD 1000000007
if (height == 0 || width == 0) return 1;
vector<vector<int>> dp(height, vector<int>(width, 0));
dp[0][0] = 1;
for (int j = 1; j < width; j++) {
for (int i = 0; i < height; i++) {
dp[i][j] = (dp[i][j] + dp[i][(j - 1)]) % MOD; //也可以直接写成dp[i][j] = dp[i][(j - 1)] % MOD;
if (i - 1 >= 0) {
dp[i][j] = (dp[i][j] + dp[i - 1][(j - 1)]) % MOD;
}
if (i + 1 < height) {
dp[i][j] = (dp[i][j] + dp[i + 1][(j - 1)]) % MOD;
}
}
}
return dp[0][(width - 1)];
}
};
加上滚动数组优化:
class Solution {
public:
/**
* @param height: the given height
* @param width: the given width
* @return: the number of paths you can reach the end
*/
int uniquePath(int height, int width) {
#define MOD 1000000007
if (height == 0 || width == 0) return 1;
vector<vector<int>> dp(height, vector<int>(2, 0));
dp[0][0] = 1;
for (int j = 1; j < width; j++) {
for (int i = 0; i < height; i++) {
dp[i][j % 2] = dp[i][(j - 1) % 2] % MOD; //注意这里不能用 dp[i][j%2] = (dp[i][j%2] + dp[i][(j - 1)%2]) % MOD; 因为dp[i][j%2]会跟之前的值混淆。如果不用滚动数组可以
if (i - 1 >= 0) {
dp[i][j % 2] = (dp[i][j % 2] + dp[i - 1][(j - 1) % 2]) % MOD;
}
if (i + 1 < height) {
dp[i][j % 2] = (dp[i][j % 2] + dp[i + 1][(j - 1) % 2]) % MOD;
}
}
}
return dp[0][(width - 1) % 2];
}
};
文章讨论了如何使用动态规划算法解决一个关于在给定高度和宽度的网格中找到从左上角到右下角独特路径数量的问题,提供了两种方法,一种是逆推,另一种是正向推进,并给出了优化版本以减少空间复杂度。
1955

被折叠的 条评论
为什么被折叠?



