力扣 62 不同路径【动态规划五步法】
全部刷题与学习记录
原题目
题目地址:62. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下
考查知识点
动态规划、dp数组的理解
好的解法
说实话,这道题第一眼直觉是用回溯做,因为剑指 12 矩阵中的路径就是相似的题目环境。但是用【代码随想录】大佬的动态规划五步法做这道题简直太棒了。在没有看题解之前,根本就不能想到这题还能用动规做,还是理解不深呀。还是一句话,只要跟下一步状态跟当前状态有关的就要往动态规划上靠。
参考:
https://mp.weixin.qq.com/s/MGgGIt4QCpFMROE9X9he_A
动态规划的dp数组并不是只局限于一维,像这道题目中的dp数组就是二维形式。
1、确定dp数组(dp table)以及下标的含义
dp数组表示的含义一般就是题目要求的答案。dp[i][j]
表示从(0,0)
到(i,j)
有多少路径。
2、确定递推公式
题目说,机器人只能往下、往右走,那么在(i,j)的机器人只能从(i-1,j)、(i,j-1)这两个方向过来。
也就是dp[i][j] = dp[i-1][j] +dp[i][j-1]
3、dp数组如何初始化
dp数组是一维时,只需要初始化dp[0],最多再加一个dp[1];那么dp数组是二维时,二维数组的边缘就是两条边了,即dp[i][0]=1
、dp[0][j]=1
。二维数组的两条边全置1的原因是机器人只能向下、向右走,要是想要到达两条边上,就得从(0,0)一直直着走。
4、确定遍历顺序
从左向右,从上到下,逐渐把dp数组每个数都算出来
5、举例推导dp数组
比如m=4, n=3
1 1 1
1 2 3
1 3 6
1 4 10
class Solution {
public:
int uniquePaths(int m, int n) {
if (m <= 1) return m;
if (n <= 1) return n;
vector<vector<int>> dp;
dp.resize(m, vector<int> (n));
//dp数组初始化
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];
}
};
int main() {
Solution so;
cout << so.uniquePaths(3, 7);
}