第九章 动态规划part02
62. 不同路径
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
思路:按照动态规划五步曲:
1、dp[i][j]含义:代表第i行第j列总共路径数
2、递推公式:dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
3、初始化:第一行和第一列路径数为1
4、遍历顺序:两个for循环遍历逐行遍历
5、举例推导
一遍ac
class Solution {
public:
int uniquePaths(int m, int n) {
int dp[n][m]; //第i行j列总共不同路径数
for(int i=0;i<n;i++){
dp[i][0]=1;
}
for(int i=0;i<m;i++){
dp[0][i]=1;
}
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[n-1][m-1];
}
};
- 时间复杂度:O(m × n)
- 空间复杂度:O(n)
解法二:采用数论的方法,从起点到终点总步数为m+n-2,其中向右走的步数为m-1,即问题转化为求m + n - 2个不同的数,随便取m - 1个数,有几种取法(组合问题)。
class Solution {
public:
int uniquePaths(int m, int n) {
long long numerator=1; //分子
int denominator=m-1; //分母
int count=m-1;
int t=m+n-2;
while(count--){
numerator*=(t--);
while(denominator!=0&&numerator%denominator==0){
numerator/=denominator;
denominator--;
}
}
return numerator;
}
};
- 时间复杂度:O(m)
- 空间复杂度:O(1)
注意如果使用分子的总乘积除以分母乘积可能超出范围。
63. 不同路径 II
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
思路:比上一题增加了障碍判断条件
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int n = obstacleGrid.size();
int m = obstacleGrid[0].size();
vector<vector<int>> dp(n, vector<int>(m, 0));
for (int i = 0; i < n; i++) {
if (obstacleGrid[i][0] == 0) dp[i][0] = 1;
else break;
}
for (int j = 0; j < m; j++) {
if (obstacleGrid[0][j] == 0) dp[0][j] = 1;
else break;
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
if (obstacleGrid[i][j] == 0) dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
else dp[i][j] = 0;
}
}
return dp[n - 1][m - 1];
}
};