题目:
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法
-
起点:(0,0);终点(m - 1,n- 1);值:从起点到目标点有多少路径
-
递推公式:dp[i][j] = dp[i - 1][j] + dp[i][j - 1];只有两个方向
-
初始化:将上和左两个边初始化
for(int i = 0; i < m; i++) dp[i][0] = 1;
for(int j = 0; j < n; j++) dp[0][j] = 1;
-
遍历顺序:根据递推公式,都是从左和上而来,那么就从左到右一层一层遍历
-
举例推导:
1 | 1 | 1 |
---|---|---|
1 | 2 | 3 |
1 | 3 | 4 |
1 | 4 | 5 |
代码
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};
优化成一维代码
class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> dp(n);
for (int i = 0; i < n; i++) dp[i] = 1;
for (int j = 1; j < m; j++) {
for (int i = 1; i < n; i++) {
dp[i] += dp[i - 1];
}
}
return dp[n - 1];
}
};
数论解法
我们知道,终点在右下角,那么一定会向下移动m - 1个格子,一定会向右移动n - 1个格子
那么这就变成了组合问题
C m + n − 2 m − 1 C^{m-1}_{m+n-2} Cm+n−2m−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;
}
};