一、动态规划理论基础
|、动态规划包含题目类型
(1)背包问题
(2)打家劫舍
(3)股票问题
(4)子序列问题
||、做一道题需要掌握(动态规划5步曲):
(1)dp数组和下标的含义
(2)确定递推公式
(3)dp数组如何初始化
(4)确定遍历顺序
(5)打印dp数组
二、动态规划三道题
509.斐波那契数
题目链接:509. 斐波那契数 - 力扣(LeetCode)
这里的步骤是:
1.确定dp[i]含义 dp[i]:第i个斐波那契数的值为dp[i]
2.递推公式:dp[i]=dp[i-1]+dp[i-2];
3.dp数组的初始化 dp[0]=1 dp[1]=1(题目要求)
4.遍历顺序:从前向后
5.(打印dp数组)
class Solution {
public:
int fib(int n) {
if(n<=1)return n;
vector<int> dp(n+1);//第n个数数组里面一共有n+1个数
dp[0]=0;dp[1]=1;
for(int i=2;i<=n;i++){//从2开始遍历了
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};
70.爬楼梯
- 确定dp数组:达到i阶,有dp[i]种方法
- 确定递推公式:dp[i]=dp[i-2]+dp[i-1]
- dp数组如何初始化:dp[1]=1,dp[2]=2;(这里的dp[0]没有意义,题目里说
1 <= n <= 45
) - 确定遍历顺序:从前向后
- 举例推导dp数组
爬到第一层楼梯:有1种方法
爬到二层楼梯:有2种方法。
那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层。
爬到第三层就:有3种方法
第二层楼梯跨两步可以到第三层楼梯,第三层楼梯再跨一步就到第四层。
爬到第四层就:有5种方法
相应的第五层:有8种方法
class Solution {
public:
int climbStairs(int n) {
if(n<=1)return n;
vector<int> dp(n+1);
dp[1]=1;dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};
746.使用最小花费爬楼梯
题目链接746. 使用最小花费爬楼梯 - 力扣(LeetCode)
1.确定dp[i]含义 dp[i]:到达第i个位置的最小
花费
2.递推公式: dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
3.dp数组的初始化 dp[0]=1 dp[1]=0
4.遍历顺序:从前向后
5.(打印dp数组)
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int>dp(cost.size()+1);
for(int i=2;i<=cost.size();i++){
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[cost.size()];
}
};
因为dp[i]要通过dp[i-1]和dp[i-2]推出来,所以:
递推公式里面的这个dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2];表达的是前面两层 每一层的花费加上前一层到这一层需要的花费,取最小的那个
当前层总花费的最小值(dp[i]):我要算前面两层已经的花费加上他们 到当前层的花费 求最小值
这样算出来的dp数组天然就是加上前面的花费的。