从今天开始正式进入DP了,今天大致了解了一下,感觉这东西是真的难,道阻且长啊!废话不多说,开始今天的内容。
动规五部曲:
1.确定dp数组以及其下标的含义
2.确定递推公式
3 dp数组如何初始化
4 确定遍历顺序
5 举例推导dp数组用来debug
以上就是dp的解题过程中必须要弄清楚的事情,在接下来的题目中,我也会说明
509. 斐波那契数:代码随想录
这道题首先dp数组的含义就是斐波那契数的值,而递推公式题目已经给出,就是dp[i] =dp[i-1] + dp[i+1],遍历的顺序显而易见是从前向后遍历,因为这一项的斐波那契数的值是依据前面的两项推出来的,所以依据上面的分析我们就可以写出如下的代码
class Solution {
public:
int fib(int n) {
if(n==0) return n;
int dp[n+1];
dp[0]=0;dp[1]=1;
for(int i=2;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};
70. 爬楼梯: 代码随想录
这道题我没有写出来,原因是因为,我没有想清楚他的递推公式怎么写,这里其实要自己稍加推导
首先dp数组的含义就是当前到达这个楼梯有多少种方案,递推公式我们可以先来看一个例子,比如到第一个楼梯需要走一步并跨一个台阶,走到第二个楼梯实际上有两种情况,第一种情况就是从第一个楼梯走一步也就是上一个台阶到达,还有就是从地面直接上两个台阶到达,其实这里你就可以发现一些端倪,再来看第三个楼梯,你是不是可以在第一个楼梯跨两个台阶到达,你也可以在第二个楼梯跨一个台阶到达,这里其实你就可以发现实际上我的递推公式就是前面两个楼梯的方案数量之和,也就是dp[i] = dp[i-1] + dp[i-2];初始化dp数组就是,一开始上第一层楼梯只需一种方案,第二层楼梯就是两种方案,所以dp[0]=1,dp[1]=2;,遍历顺序就是从前向后遍历,接着来看具体的代码的实现
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1);
dp[0]=1;dp[1]=2;
for(int i=2;i<n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n-1];
}
};
这里主要是递推关系比较难想,如果你是一开始学dp的话
746. 使用最小花费爬楼梯:代码随想录
这道题目我大致知道应该怎么去做,但是就是写不出代码,归根结底还是五部曲没有弄清楚,首先就是dp数组他的意思应该就是到达这个楼梯的最小花费,而下标代表的就是当前楼梯,而递推公式,我们知道题目说你开始可以任意选择你是在下标为1还是0的台阶上开始爬,这里还需注意的是我们的cost数组是你爬到下一层的时候才加上这个cost[i]的花费,否则如果你只是到达这个楼梯是不需要加的,还有就是楼顶应该是处于n+1的位置,对应到数组的下标应该是n,我们先想想我们当前层是不是只能由i-1层跨一步到达和i-2层跨两步到达,对吧,那么他们跨到当前层的费用是不是分别是dp[i-1]+cost[i-1]和dp[i-2]+cost[i-2]啊,然后题目要求最小的费用,是不是只要取他们的最小值就可以了啊,所以本题的递推公式就是:dp[i] = min(dp[i-1]+cost[i-1],dp[i-2] + cost[i -2]),由于题目说了你一开始可以任意选择是在0还是1,所以dp[0]=0,dp[1]=0,注意我这里是因为将所有的台阶的下标都减了1,相当于下标从0开始,所以返回值是dp[n]代表楼顶,代码如下
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n=cost.size();
int dp[n+1];
dp[0]=0;dp[1]=0;
for(int i=2;i<=n;i++){
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[n];
}
};
这个dp是真的很有挑战性,加油啊!