虽然一看就很像典型的动态规划求最短路径的题型,不过这题求的是路径的数量,也即是说求的是有多少种符合要求的走法。就像走台阶那个题,求的是走法的数量。
和这个不一样(不过思路差不多):
leetcode 第 64 题:最小路径和(C++)_qq_32523711的博客
LeetCode第 120 题:三角形最小路径和(C++)_qq_32523711的博客
对于当前位置来说:
如果当前位置在边界上,右边界或者下边界,那这是只有一种选择(在下边界,就只能往右走;在右边界,就只能往下走)
当前位置不在边界上,那么根据题意可以选择往下走或者往右走。
不难得出,每一个方格的前一步只能是它的左边或者上面二选一(不是第一行/第一列):
f
[
m
−
1
]
[
n
−
1
]
=
=
f
[
m
−
2
]
[
n
−
1
]
+
f
[
m
−
1
]
[
n
−
2
]
f[m-1][n-1] == f[m-2][n-1] + f[m-1][n-2]
f[m−1][n−1]==f[m−2][n−1]+f[m−1][n−2]
第一行或者第一列特殊处理。详见代码。
先写常规动态规划吧,使用一个二维数组:
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> f(m, vector<int>(n, 0));
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
if(i == 0 && j == 0) f[i][j] = 1;//左上角
else if(i == 0) f[i][j] = f[i][j-1];//第一行
else if(j == 0) f[i][j] = f[i-1][j];//第一列
else f[i][j] = f[i-1][j] + f[i][j-1];
}
}
return f[m-1][n-1];
}
};
简化初始化:
class Solution {
public:
int dp[110][110];
int uniquePaths(int m, int n) {
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j){
if(i == 1 && j == 1) dp[i][j] = 1;
else dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m][n];
}
};
来进行优化吧,做过前面贴的两题就知道,二维数组是没有必要的,使用两行的滚动数组或者一维数组都可以解决问题,那就一步到位使用一维数组吧:
class Solution {
public:
int dp[110];
int uniquePaths(int m, int n) {
dp[1] = 1;
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j)
dp[j] += dp[j-1];
}
return dp[n];
}
};
另外,其实这个问题用数学方法就可以解:
机器人一定会走m+n-2
步,即从m+n-2
中挑出m-1
步向下走即可,即
C
m
+
n
−
2
m
−
1
C_{m+n-2}^{m-1}
Cm+n−2m−1。