1.什么是动态规划?
答:动态规划(Dynamic Programming) 简称DP,在动规划中每一个状态一定是由上一个状态推导出来的。
2. 动态规划的解题步骤是什么?
答:1.确定dp数组(dp table)以及下标的含义。2.确定递推公式。3.dp数组如何初始化。4.确定遍历顺序。5.举例推导dp数组。
动规五部曲:
使用一个一维dp数组来保存递归结果
1. 确定dp数组以及下标的含义
dp[i]的定义为:第i个数的斐波那契数值是dp[i]。
2. 确定递推公式
状态转移方程dp[i] = dp[i - 1] + dp[i - 2]
3. dp数组如何初始化
题目已经给定初始化了:dp[0] = 0; dp[1] = 1.
4. 确定遍历顺序
由递推公式dp[i] = dp[i -1] + dp[ i - 2]可知,dp[i]是依赖于dp[i - 1]和dp[ i - 2]的,所以遍历的顺序一定是从前往后遍历的。
5. 举例推导dp数组
当 N = 10 如下:
0 1 1 2 3 5 8 13 21 34 55
class Solution {
public:
int fib(int n) {
if(n <= 1) return n; // 当n为0或1时,直接返回n本身
vector<int> dp(n + 1); // 初始化一个大小为n+1的vector,用于存储斐波那契数列
dp[0] = 0; // 初始化dp[0]为0
dp[1] = 1; // 初始化dp[1]为1
for(int i = 2 ; i <= n ; i++){ // 从2开始遍历到n
dp[i] = dp[i -1] + dp[i - 2]; // dp[i]等于前两项之和
}
return dp[n]; // 返回第n项的值
}
};
动规五部曲:
使用一个一维dp数组来记录不同楼层的状态。
1. 确定dp数组以及下标的含义
dp[i]的定义为:爬到第i层楼梯,有dp[i]种方法。
2. 确定递推公式
状态转移方程dp[i] = dp[i - 1] + dp[i - 2]
3. dp数组如何初始化
dp[1] = 1; dp[2] = 2.
4. 确定遍历顺序
由递推公式dp[i] = dp[i -1] + dp[ i - 2]可知,dp[i]是依赖于dp[i - 1]和dp[ i - 2]的,所以遍历的顺序一定是从前往后遍历的。
5. 举例推导dp数组
当 N = 5 如下:
dp[i] : 1 2 3 5 8
下标i: 1 2 3 4 5
class Solution {
public:
int climbStairs(int n) {
if(n <= 1) return n; // 当n=0或n=1时,结果为n
vector<int> dp(n+1); // 定义一个长度为n+1的数组dp,存储到达每个台阶的方法数
dp[1] = 1; // 到达第1个台阶的方法数为1
dp[2] = 2; // 到达第2个台阶的方法数为2
for(int i = 3 ; i <=n ; i++){ // 从第3个台阶开始计算
dp[i] = dp[i - 1] + dp[i - 2]; // 到达第i个台阶的方法数等于到达第i-1个台阶的方法数和到达第i-2个台阶的方法数之和
}
return dp[n]; // 返回到达第n个台阶的方法数
}
};
动规五部曲:
1. 确定dp数组以及下标的含义
dp[i]的定义为:到达第i台阶所花费的最小体力为dp[i]。
2. 确定递推公式
dp[i - 1]跳到dp[i] 需要花费dp[i-1] + cost[i - 1]
dp[i - 2]跳到dp[i] 需要花费dp[i-2] + cost[i - 2]
选择最小的:
dp[i] = min(dp[i - 1]+ cost[i -1],dp[i - 2]+ cost[i - 2])
3. dp数组如何初始化
由题意:dp[0] = 0; dp[1] = 0.
4. 确定遍历顺序
模拟台阶,而且dp[i] 由dp[i - 1]和dp[i-2]推出,所以是从前到后遍历cost数组。
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> dp(cost.size() + 1); // 定义一个长度为cost.size()+1的vector
dp[0] = 0; // 初始化dp[0]为0
dp[1] = 0; // 初始化dp[1]为0
for(int i = 2 ; i <=cost.size() ; i++){ // 从i=2开始遍历cost数组
// dp[i]表示到达第i个台阶的最小花费
// 由于可以从第i-1个台阶或者第i-2个台阶到达第i个台阶,因此取两者的最小值
dp[i] = min(dp[i - 1] + cost[i - 1],dp[i - 2] + cost[i - 2]);
}
return dp[cost.size()]; // 返回到达最后一个台阶的最小花费
}
};
[代码随想录]