算法第28天|动态规划:基础理论、斐波那契数、爬楼梯、使用最小花费爬楼梯

今日总结

1、动态规划的五部曲要复习
2、动态规划的dp数组的含义及下标一定要定义清楚
3、动态规划的dp数组的递推公式一定要根据题目进行分析
4、动态规划的初始化一定要分析清楚(一定要在递推公式确定后再进行初始化分析)

动态规划的基础理论

1、动态规划是什么

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

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分与贪心,贪心没有状态推导,而是从局部直接选择最优

2、动态规划的解题步骤

状态转移公式(递推公式)很重要,但是动态规划不仅仅只有递推公式

动态规划的五部曲

(1)确定dp数组(dp table)以及下标的含义

(2)确定递推公式

(3)dp数组如何初始化

(4)确定遍历顺序

(5)举例推导dp数组

先确定递推公式再考虑初始化的原因:

一些情况是递推公式决定dp数组如何初始化

3、动态规划如何debug

最好的方式就是把dp数组打印出来,看看是不是按照自己思路推导的

(1)做动态规划的题目,写代码前一定要把状态转移在dp数组上的具体情况模拟一遍,做到心中有数,确定最后推出的是想要的结果

(2)然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的一样。

(3)如果打印的dp数组和自己推导的一样,就是自己的递归公式、初始化、遍历顺序有问题

(4)如果和自己预先模拟推导的不一,就是代码的实现细节有问题

斐波那契数

题目链接:509. 斐波那契数 - 力扣(LeetCode)

整体思路:

1、使用递归的方式做

2、使用动态规划dp做

dp五部曲

(1)确定dp数组及下标的含义

dp[i]的定义为:第i个数的斐波那契数值为dp[i];

(2)确定递推公式(就是当前的dp值与前边的有什么关系)

状态转移方程dp[i] = dp[i-1]+dp[i-2];

(3)qp数组初始化

dp[0]=0,dp[1]=1;

(4)确定遍历顺序

从状态转移方程可以看出当前dp[i]依赖于i-1,i-2,所以是从前往后遍历

(5)举例推导dp数组

当N=10:0,1,1,2,3,5,8,13,21,34,55

整体代码:

1、递归

cpp 复制代码
class Solution {
public:

    //1、确定递归的返回值、输入值
    //返回值当前的计算结果
    //输入值:当前的N
    int digui(int N)
    {
        //确定停止条件
        if(N==1)return 1;
        else if(N==0)return 0;
        //确定单层递归逻辑
        return digui(N-1)+digui(N-2);
    }
    int fib(int n) {
        return digui(n);
        
    }
};

2、动态规划(dp)

cpp 复制代码
class Solution {
public:
    int fib(int n) {
        //1、确定dp数组及下标含义:下标为当前的斐波那契数值
        vector<int>dp(n+1,0);
        //2、确定递推公式dp[i] = dp[i-1]+dp[i-2]
        //3、dp数组初始化
        if(n<1)return 0;
        dp[0]=0;
        dp[1]=1;
        if(n<=1)return n;
        //4、确定遍历顺序:前-->后
        //5、举例推导
        for(int i=2;i<n+1;i++)
        {
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
};

爬楼梯

题目链接:70. 爬楼梯 - 力扣(LeetCode)

整体思路:

第一层楼梯:1

第二层楼梯:1+1;2

第三层楼梯:1+1+1(2,1,1);2+1(2,2,1);1+2(1,1,2)

第四层楼梯:1+1+1+1(3,1,1);2+1+1(3,2,1);1+2+1(3,3,1);1+1+2(2,1,2);2+2(2,2,2)

可以看出,当前i层的楼梯是通过i-1层的楼梯+1或者i-2层的楼梯+2的全部方法,所以当前层是与前边层的状态有关的,可以使用动态规划dp

(1)确定dp数组及下标

dp数组是当前楼梯的方法数,下标是当前楼梯的层数+1

(2)确定dp数组的递推公式

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

(3)确定dp数组的初始化

dp[1]=1.dp[2]=2

(4)确定dp数组遍历方向:从前往后

(5)举例

整体代码:

cpp 复制代码
class Solution {
public:
    int climbStairs(int n) {
        //(1)确定dp数组及下标

                //dp数组是当前楼梯的方法数,下标是当前楼梯的层数
    vector<int>dp(n+1,0);
    if(n==1)return 1;

        //(2)确定dp数组的递推公式

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

        //(3)确定dp数组的初始化

                //dp[1]=1.dp[2]=2
    dp[1]=1;
    dp[2]=2;
    for(int i=3;i<n+1;i++)
    {
        dp[i] = dp[i-1]+dp[i-2];
    }

        //(4)确定dp数组遍历方向:从前往后
    return dp[n];
        //(5)举例  
    }
};

使用最小花费爬楼梯

题目链接:746. 使用最小花费爬楼梯 - 力扣(LeetCode)

整体思路:

由题目可知:

(1)可以从0级台阶、1级台阶进行向上爬1级或者两级,支付当前台阶的cost

(2)最终到达楼梯顶,也就是需要通过最后一级台阶或者倒二台阶

(3)需要花费最少的cost,

(4)所以当前层最少一定是前边花费的最小-->动态规划

使用dp动态规划

(1)dp数组的含义:dp[i]表示当前层花费最少的cost

(2)dp数组的状态转移方程

dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])

(3)dp数组的初始化

dp[0]=cost[0];

dp[1] =cost[1];

(4)dp数组的遍历方式:从前到后

(5)举例

整体代码:

cpp 复制代码
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        /*
        (1)dp数组的含义:dp[i]表示当前层花费最少的cost
                (2)dp数组的状态转移方程
                                dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
                (3)dp数组的初始化
                                dp[0]=cost[0];
                                dp[1] =cost[1];
                (4)dp数组的遍历方式:从前到后
        */
        vector<int>dp(cost.size()+1);
        dp[0] = 0;
        dp[1] = 0;
        for(int i=2;i<cost.size()+1;i++)
        {
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[cost.size()];
    }
};
相关推荐
OKkankan34 分钟前
string类的模拟实现
开发语言·数据结构·c++·算法
虾饺爱下棋2 小时前
FCN语义分割算法原理与实战
人工智能·python·神经网络·算法
Eloudy5 小时前
简明量子态密度矩阵理论知识点总结
算法·量子力学
点云SLAM5 小时前
Eigen 中矩阵的拼接(Concatenation)与 分块(Block Access)操作使用详解和示例演示
人工智能·线性代数·算法·矩阵·eigen数学工具库·矩阵分块操作·矩阵拼接操作
算法_小学生7 小时前
支持向量机(SVM)完整解析:原理 + 推导 + 核方法 + 实战
算法·机器学习·支持向量机
iamlujingtao7 小时前
js多边形算法:获取多边形中心点,且必定在多边形内部
javascript·算法
算法_小学生7 小时前
逻辑回归(Logistic Regression)详解:从原理到实战一站式掌握
算法·机器学习·逻辑回归
DebugKitty8 小时前
C语言14-指针4-二维数组传参、指针数组传参、viod*指针
c语言·开发语言·算法·指针传参·void指针·数组指针传参
qystca8 小时前
MC0241防火墙
算法
行然梦实10 小时前
粒子群优化算法(Particle Swarm Optimization, PSO) 求解二维 Rastrigin 函数最小值问题
算法·机器学习·数学建模