【算法模板】动态规划(基础DP篇)(一)

简介: 【算法模板】动态规划(基础DP篇)(一)

什么是动态规划?

动态规划 (英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题。(百度百科得到的答案)


简单的就是说:用简单的方法来解决复杂的问题!


核心思想:


动态规划的核心就是 有记忆,减少不必要的计算!


动态规划的做题方法

一般我们在做动态规划这种题的时候一般会有一下这几个步骤:


定义一个的dp数组。

dp数组的初始化。

列举动态规划推导公式。

进行循环遍历逐步改变dp数组的值,直道循环结束能获取我们所需要的值即可。

我们只要上述的几个步骤没有出现什么问题的话,那么这个这个题也就是手到擒拿了!


而上述步骤中比较难的就是 动态规划推导公式 的推导,一般在做题时我们很容易的知道这个题是用动态规划来解决这个问题。但是每次就会卡到动态规划推导公式这个地方(不要问我为什么5555)。所以这个也是我们需要提高的地方!!!


给大家一些 建议 ,在做动态规划题的时候 一定要自己推导自己的动态规划推导公式 ,就算写不出来我们在看题解的时候也可以那我们自己推导出来的公式和官方的公式进行一个对比,每次在做题的时候只要能保证这点,则以后的进步就会越来越大!!!


一维DP

简介

在上面我们已经知道了什么是 DP 了,那么什么又是 一维DP 呢?


一维DP:


通常的讲 一维DP 就是通过一维的数组来满足 推导公式 的一个求解。


int[] dp = new int[10];//则表示创建了一个长度为10的一维DP数组。
//例如:推导公式
dp[i] = max(dp[i - 2] + dp[i - 1] , dp[i])//这个就是一个比较简单的一维DP推导公式!


走进一维DP

上述中我们知道了什么是 一维DP ,那我们就要来走进这个它,并且征服它!同学们来看下面的例题吧。


例题:


509. 斐波那契数


题目:


斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:


F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

示例:


输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
1


做题步骤:


还记得我们第一步需要怎么来分析的吗?


第一步我们需要确定这题的 DP 数组该怎么去创建?


第二步需要我们推导出本题的 DP 公式。


第三步进行循环得到我们需要的结果。


思路:


通过做题步骤我们能知道这个 DP数组 的长度是 n + 1 (因为需要从0开始到n,所以长度也就是 n + 1 )


题目所说从 1 后面开始每一项的数字都是前两项的和。通过解析这句话我们能知道我们的 循环是从2开始,到n结束 。而推导公式则就是:


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


当我们完成上述的步骤时接下来就是将这题给实现了。


代码:


Python版本:


class Solution:
    def fib(self, n: int) -> int:
        if n < 2:
            return n
        dp = [0]* (n + 1)
        dp[1] = 1
        for i in range(2 , n + 1):
            dp[i] = dp[i - 1] + dp[i - 2]
        return dp[n]


Java版本:


class Solution {
    public int fib(int n) {
        if (n == 0) return 0;
        if (n == 1) return 1;
        int[] dp = new int[n + 1];
        dp[1] = 1;
        for (int i = 2; i < n + 1; i++){
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
}


我们做了一个比较简单的DP题,那我们再来看另外一个简单的DP问题吧


题目:


746. 使用最小花费爬楼梯


给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。


你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。


请你计算并返回达到楼梯顶部的最低花费。


示例:


输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15


做题步骤:


DP数组 的创建。


推导出本题的 DP 公式。


进行循环。


思路:


在题目的含义中我们已经知道了 用最小的花费来达到顶楼! 则我们需要创建的 DP数组 长度就为 n + 1 (第n 个下标代表的是楼顶)。则也能得到动态规划的公式和循环的开始点和结束点!


动态规划公式:


dp[i] = min(dp[i-1]+cost[i-1],cost[i-2]+dp[i-2])//从4开始的循环公式
dp[i] = min(dp[i - 1] + cost[i - 1], cost[i - 2] )//当i是等于3的时候判断方程式
dp[i] = min(cost[i - 1], cost[i - 2])//等于2的时候的一个公式


代码:


Python版本


class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        dp = [0 for i in range(len(cost)+1)]
        for i in range(2,len(cost)+1):
            if i ==3 :
                dp[i] = min(dp[i - 1] + cost[i - 1], cost[i - 2] )
            elif i ==2 :
                dp[i] = min(cost[i - 1], cost[i - 2])
            else:
             dp[i] = min(dp[i-1]+cost[i-1],cost[i-2]+dp[i-2])
        return dp[len(cost)]


Java版本:


class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] dp  = new int[cost.length + 1];
        for(int i = 2; i < cost.length + 1; i ++){
            if (i == 2){
                dp[i] = Math.min(cost[i - 1], cost[i - 2]);
            }
            else if (i == 3){
                dp [i] = Math.min(cost[i - 2] , dp[i - 1] + cost[i - 1]);
            }else{
                dp[i] = Math.min(cost[i - 1] + dp[i - 1] , cost[i - 2] + dp[i - 2]);
            }
        }
        return dp[cost.length];
    }
}



OK,例题看完了,接下来就是来看习题了哦!!!


模块练习题


相关文章
|
1月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
2月前
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
60 8
|
1月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
1月前
|
算法 Java 测试技术
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
这篇文章介绍了基于动态规划法的三种算法:解决背包问题的递归和自底向上实现、Warshall算法和Floyd算法,并提供了它们的伪代码、Java源代码实现以及时间效率分析。
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
|
2月前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
62 2
|
2月前
|
算法 程序员 Python
算法小白到大神的蜕变之路:Python分治法、贪心、动态规划,一步步带你走向算法巅峰!
【7月更文挑战第9天】探索算法之旅,以Python解锁编程高手之路。分治法如二分查找,将复杂问题拆解;贪心算法解决活动选择,每次选取局部最优;动态规划求斐波那契数列,避免重复计算,实现全局最优。每一步学习,都是编程能力的升华,助你应对复杂挑战,迈向算法大师!
35 1
|
15天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
15天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。
|
16天前
|
资源调度 算法
基于迭代扩展卡尔曼滤波算法的倒立摆控制系统matlab仿真
本课题研究基于迭代扩展卡尔曼滤波算法的倒立摆控制系统,并对比UKF、EKF、迭代UKF和迭代EKF的控制效果。倒立摆作为典型的非线性系统,适用于评估不同滤波方法的性能。UKF采用无迹变换逼近非线性函数,避免了EKF中的截断误差;EKF则通过泰勒级数展开近似非线性函数;迭代EKF和迭代UKF通过多次迭代提高状态估计精度。系统使用MATLAB 2022a进行仿真和分析,结果显示UKF和迭代UKF在非线性强的系统中表现更佳,但计算复杂度较高;EKF和迭代EKF则更适合维数较高或计算受限的场景。
|
18天前
|
算法
基于SIR模型的疫情发展趋势预测算法matlab仿真
该程序基于SIR模型预测疫情发展趋势,通过MATLAB 2022a版实现病例增长拟合分析,比较疫情防控力度。使用SIR微分方程模型拟合疫情发展过程,优化参数并求解微分方程组以预测易感者(S)、感染者(I)和移除者(R)的数量变化。![]该模型将总人群分为S、I、R三部分,通过解析或数值求解微分方程组预测疫情趋势。