一文读懂动态规划问题

动态规划五部曲

动态规划,英文: Dynamic Programming, 简称DP,如果某一个问题由很多重叠子问题,使用动态规划是最有效的。

所谓动态规划就是,在解决一个问题的过程中,将其分解为很多个小的部分,环环相扣。最典型的一个例子,我们入门编程时都学习过的斐波那契数,每个数都是由前面的两个数字推导出来的,也就是所谓的前一个状态。

动态规划解题步骤

在我刚接触动规题目的时候,比如说做01背包的问题,去把状态转移公式背下来,然后照着这样去改改开始写代码,把题目做完之后可能都不知道后一个状态是如何推导而来的。

对于动态规划的问题,如果我们在分析题目的时候能够看出来可以转换为动态规划来求解的话一般就比较好解决了。对于此类问题我一般拆解为五步。简称动归五部曲

1.确定dp数组 以及其下标的含义

2.确定递推公式

3.dp数组如何初始化

4.确定遍历顺序

5.举例推导dp数组

在这里我给个建议,就是在做题的时候在我们把dp数组推导出来后,去将它打印出来,看看究竟是不是按照自己的思路推导的!就算出现问题的时候我们也可以很直观的看出来问题出在哪里,当出现错误的时候不要去胡乱的修改,先去分析以上的五步到底是哪里出了问题,有没有真正理解dp数组的含义。

实战演练

  1. 爬楼梯

如果没有接触过的话乍一看会感觉没有思路,既然每次只能爬1或2层台阶,爬到第一层楼有一种方法,爬到第二层楼就是有两种方法(直接爬两层或者分为两次一次爬一层),如何与动态规划结合起来呢,既然一次只能爬1或2层,那么不管是哪层楼,是不是只能由它的前一层或前两层爬过来。

分析到这里我们按照前面讲的动归五部曲:

1.确定dp数组以及下标的含义

dp[i]就是爬到第i层楼有dp[i]种方法

2.确定递推公式

不管哪一层楼都只能由它的前一层或前两层爬过来,那么很简单

dp[i] = dp[i-1]+dp[i-2].

在推导的时候,要时刻想着dp[i]的含义。

3.dp数组如何初始化

dp[i]的含义是爬到第i层楼,有dp[i]种方法。那么本题中我们应该从哪里开始遍历呢,dp[0]有没有含义呢,很明显的就可以得到dp[1] = 1;dp[2] = 2 那么根据状态转移方程,是不是要将dp[0]初始化为1呢,这显然是不正确的。因为我们初始状态就是在第0层,也就是说dp[0]是没有意义的,所以在这道题中 应该初始化dp[1] = 1,dp[2] = 2.

4.遍历顺序

我们已经将dp[1]和dp[2]初始化后,那么就是从第三层楼开始遍历,一直推导到我们所需要求的楼层。

5.举例推导dp数组

前面我们已经说了,在推导过程中将每一个状态都打印出来,我们可以举例推导dp[3] = 3,都是符合的,所以本题到这里按照五部曲已经解决。当我们熟悉了这个过程之后是非常快的。

class Solution {
public:
    int climbStairs(int n) {
        //1. 确定dp数组的含义 dp[i] 表示爬到第i层楼一共有多少种方法
        //2. 确定递推公式 dp[i] = dp[i-1] + dp[i-2];
        //3. dp数组初始化  dp[1] = 1, dp[2] = 2
        //4. 遍历顺序 从第3层楼开始遍历
        //5. 举例推导验证
        vector<int> dp(n+1);
        if(n<=1) return n;
        dp[1] = 1,dp[2] = 2;
        for(int i= 3;i<=n;i++ )
        {
            dp[i] = dp[i-1]+dp[i-2];
        }  
        return dp[n];
        
​
    }
};

以上就是对于动态规划问题的基本阶梯思路 后续还会在本帖中更新相关动态规划问题的题解。

  • 37
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值