动态规划入门和应用示例

文章目录

  • 前言
  • 斐波那契数列
  • 爬楼梯
  • 总结
    • 优点:
    • 缺点:


前言

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的数学方法。它主要用于解决一类具有重叠子问题和最优子结构性质的问题。通过把原问题分解为相对简单的子问题的方式,动态规划可以求得复杂问题的最优解。

动态规划的基本思想是将一个复杂的问题分解为若干个相对简单的子问题,通过求解这些子问题,并将它们的解存储起来,以便在求解更大的问题时能够重复利用这些解,从而避免大量的重复计算,提高算法的效率。

以下是动态规划入门的几个关键要点:

  1. 核心思想
  • 动态规划的核心思想是利用过去的数据解决现在的问题。通过分解原问题为相互重叠的子问题,并解决这些子问题来得到原问题的解。
  • 动态规划的关键在于“状态”和“状态转移方程”。状态表示问题的某个阶段,而状态转移方程描述了从一个状态转移到另一个状态的规则。
  1. 基本步骤
  • 定义状态:明确问题中的状态,即子问题的表示方式。
  • 状态转移方程:建立状态之间的关系,即如何从当前状态转移到下一个状态。
  • 初始化:为状态的初始值设定合理的默认值。
  • 计算顺序:按照某种顺序(通常是自底向上或自左向右)计算所有状态的值。
  • 返回值:返回最终状态的值作为问题的解。
  1. 应用实例
  • 斐波那契数列:经典的动态规划问题,可以通过存储已计算的斐波那契数来避免重复计算。
  • 背包问题:给定一组物品和背包容量,如何选择物品使得背包内物品的总价值最大。
  • 最短路径问题:在图论中,求从一个顶点到另一个顶点的最短路径。
  • 股票买卖问题:计算在给定的股票价格序列中,通过买入和卖出股票能够获得的最大利润。
  1. 实践建议
  • 从简单的问题开始,逐步增加难度,逐步熟悉和掌握动态规划的思想和方法。
  • 多做练习,尤其是经典问题的练习,有助于深入理解动态规划的应用和技巧。
  • 结合实际问题,思考如何将其转化为动态规划问题,并设计合适的状态和状态转移方程。

总之,动态规划是一种强大而灵活的数学工具,适用于求解各种优化问题。通过不断学习和实践,你可以逐渐掌握这一技术并应用于实际问题中。


斐波那契数列

斐波那契数列是一个常见的动态规划问题,其定义为:每个数是前两个数之和,序列的开始两个数是0和1。例如,斐波那契数列的前几个数是:0, 1, 1, 2, 3, 5, 8, 13, 21, …

在C++中,我们可以使用动态规划来高效地计算斐波那契数列中的数。下面是一个简单的C++代码示例,它使用动态规划来计算第n个斐波那契数:

#include <bits/stdc++.h>int fibonacci(int n) {if (n <= 1) {return n;}std::vector<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];
}int main() {int n;std::cout << "Enter the position in the Fibonacci sequence: ";std::cin >> n;std::cout << "Fibonacci number at position " << n << " is: " << fibonacci(n) << std::endl;return 0;
}

在这个代码中,我们创建了一个dp数组来存储斐波那契数列的每一项。数组的索引表示斐波那契数列中的位置,数组的值表示对应位置的斐波那契数。我们从位置2开始迭代,并使用前两项的值来计算当前项的值。最后,我们返回dp[n],即第n个斐波那契数。

注意,这个实现方法对于较大的n值可能不是最高效的,因为它使用了一个大小为n+1的数组来存储中间结果。对于更大的n值,我们可以考虑使用迭代方法而不是动态规划,因为迭代方法只需要存储前两项的值,而不是整个数组。下面是一个迭代方法的示例:

int fibonacci(int n) {if (n <= 1) {return n;}int a = 0, b = 1, temp;for (int i = 2; i <= n; ++i) {temp = a + b;a = b;b = temp;}return b;
}

在这个迭代版本中,我们只使用了三个变量abtemp来依次计算斐波那契数列中的每一项,而不是使用整个数组。这种方法在内存使用上更加高效,特别是对于非常大的n值。

爬楼梯

C++ 动态规划入门的一个经典例子就是“爬楼梯”问题。这个问题描述如下:

假设你正在爬楼梯,需要 n 阶你才能到达楼顶。每次你都可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

为了解决这个问题,我们可以使用动态规划。我们可以定义一个数组 dp,其中 dp[i] 表示到达第 i 阶楼梯的方法数。根据题目,我们知道:

  • dp[0 = 1(只有1种方法到达第1阶楼梯,即爬1个台阶)
  • dp[1] = 2(有2种方法到达第2阶楼梯,即爬1个台阶两次或爬2个台阶一次)

对于 i >= 2 的情况,到达第 i 阶楼梯的方法数等于到达第 i-1 阶楼梯的方法数(再爬1个台阶)加上到达第 i-2 阶楼梯的方法数(再爬2个台阶)。因此,我们可以得到状态转移方程:

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

下面是一个使用 C++ 实现的例子:

#include <bits/stdc++.h>int climbStairs(int m) {if (m <= 2) {return n;}//定义m级台阶走法数组int dp[m];//一级台阶1种走法dp[0] = 1;  //二级台阶2种走法dp[1] = 2;  //第i级台阶走法=第i-1级台阶走法+第i-2级台阶走法for (int i = 2; i < m; ++i) {  dp[i] = dp[i - 1] + dp[i - 2];  }  return dp[m-1];
}int main() {int n;std::cout << "Enter the number of stairs: ";std::cin >> n;std::cout << "Number of ways to climb " << n << " stairs: " << climbStairs(n) << std::endl;return 0;
}

总结

以下是动态规划的主要优缺点:

优点:

  1. 高效性:动态规划通过存储子问题的解,避免了重复计算。对于具有大量重叠子问题的情况,动态规划可以显著减少计算量,提高算法效率。

  2. 全局最优解:动态规划通过自底向上的方式,逐步构建问题的解,保证了最终得到的是全局最优解。在解决优化问题时,动态规划是一种非常有效的工具。

  3. 结构清晰:动态规划通常将问题分解为一系列相互关联的子问题,并按照一定的顺序逐步求解。这种分解方式使得问题的结构更加清晰,便于理解和实现。

  4. 适用范围广:动态规划可以应用于多种类型的问题,包括背包问题、最长公共子序列、最短路径问题等。通过合理的状态定义和状态转移方程设计,动态规划可以很好地解决这些问题。

缺点:

  1. 空间复杂度较高:动态规划通常需要存储大量的子问题解,以便在后续计算中重复利用。这可能导致较高的空间复杂度,特别是在处理大规模问题时,可能需要消耗大量的内存空间。

  2. 设计难度较大:动态规划的核心在于状态的定义和状态转移方程的设计。对于复杂的问题,如何选择合适的状态和状态转移方程可能是一个挑战。设计不当可能导致算法的正确性无法保证或效率较低。

  3. 问题依赖性强:动态规划通常针对特定类型的问题进行设计,对于不同类型的问题可能需要采用不同的策略和方法。这使得动态规划具有一定的局限性,不适用于所有类型的问题。

  4. 可能不是最优解法:虽然动态规划通常能够得到全局最优解,但在某些情况下,可能存在其他更高效的算法或启发式方法来解决相同的问题。因此,在选择算法时需要根据问题的特点进行权衡和比较。

综上所述,动态规划具有高效性和全局最优解的优点,但也可能存在空间复杂度较高和设计难度较大的缺点。在实际应用中,需要根据问题的特点选择合适的算法,并充分利用动态规划的优势来解决实际问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql允许ip远程访问

1.找到自己mysql所安装数据库的bin目录地址 例如&#xff1a;G:\mysql-5.7.23-winx64\bin 2.搜索cmd打开命令提示符进入这个bin目录 注意:如果目录不在c盘需要切换盘符。 切换访问步骤如下&#xff08;如上例子在G盘&#xff09; &#xff08;1&#xff09;先输入 g: &am…

Golang | Leetcode Golang题解之第55题跳跃游戏

题目&#xff1a; 题解&#xff1a; // 贪心算法 func canJump(nums []int) bool {cover : 0n : len(nums)-1for i : 0; i < cover; i { // 每次与覆盖值比较cover max(inums[i], cover) //每走一步都将 cover 更新为最大值if cover > n {return true}}return false } …

CHATGPT对写作业的好处

原文&#xff1a;chatGPT对写作业的好处 - 夸智网 本文目录一览1、chatGPT对写作业的好处2、chatGPT批改作业3、chatGPT完成作业4、chatGPT写作业水平超过大学生5、美国大学生用chatGPT写作业大家好&#xff0c;今天来为您分享chatGPT对写作业的好处的一些知识&#xff0c;本文…

如何买到“30元以下”的免备案服务器?

对于预算有限的个人和小型企业来说&#xff0c;30 元以下免备案服务器的价格非常亲民。用户可以以极低的成本获得所需的服务器资源&#xff0c;这对创业者、个人开发者、学生和站长来说简直不要太划算&#xff0c;毕竟配置可以升级真不够后面再付费升级也行。 何为“免备案”&…

Android双向认证配置过程

1&#xff08;可以绕过&#xff09;准备过程 为了让这个教程可以一直复用&#xff0c;打算直接写一个双向认证的APP作为素材。 工具&#xff1a; ●protecle&#xff08;签名文件转换&#xff09; ●keytool&#xff08;java自己就有&#xff09; ●openssl&#xff08;apache里…

NLP transformers - 文本分类

Text classification 文章目录 Text classification加载 IMDb 数据集Preprocess 预处理EvaluateTrainInference 本文翻译自&#xff1a;Text classification https://huggingface.co/docs/transformers/tasks/sequence_classification notebook : https://colab.research.googl…

FPGA 以太网概念简单学习

1 MAC和PHY 从硬件的角度来说&#xff0c;以太网接口电路主要由 MAC &#xff08; Media Access Control &#xff09;控制器和物理层接口 PHY&#xff08;Physical Layer &#xff0c; PHY &#xff09;两大部分构成。 MAC 指媒体访问控制子层协议&#xff0c;它和 PHY 接…

创建获利段

事务代码&#xff1a;KE21N BAPI&#xff1a;BAPI_COPAACTUALS_POSTCOSTDATA 前台操作&#xff1a; 表是业务配置的 配置路径&#xff1a; 代码&#xff1a;BAPI不返回生成的凭证号和获利段&#xff0c;需要通过增强或者读表获取 ls_copa_data-record_id 000001.ls_co…

Agent AI智能体在未来,一定与你我密不可分

随着Agent AI智能体的逐渐成熟&#xff0c;人工智能应用的不断深入与拓展&#xff0c;相信在不久的将来&#xff0c;他与你我的生活一定是密不可分的。 目录 ​编辑 1 Agent AI智能体是什么&#xff1f; 2 Agent AI在语言处理方面的能力 2.1 情感分析示例 2.2 文本分类任…

Spring - 5 ( 8000 字 Spring 入门级教程 )

一&#xff1a;Spring IoC&DI 1.1 方法注解 Bean 类注解是添加到某个类上的&#xff0c; 但是存在两个问题: 使用外部包里的类, 没办法添加类注解⼀个类, 需要多个对象, ⽐如多个数据源 这种场景, 我们就需要使用方法注解 Bean 我们先来看方法注解如何使用: public c…

Unity 踩坑记录 Rigidbody 刚体重力失效

playerSetting > physics > Gravity > 设置 Y 的值为负数

前端canvas项目实战——在线图文编辑器(九):逻辑画布

目录 前言一、 效果展示二、 实现步骤1. 调整布局&#xff0c;最大化利用屏幕空间2. 添加逻辑画布3. 添加遮罩4. 居中显示逻辑画布5. 一个容易被忽视的bug点 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们实现了一组通用的功能按钮&#xff1a;复制、删除、锁定…

FreeRTOS之列表

1.FreeRTOS的列表和列表项十分重要。列表类相当于链表&#xff0c;列表项则相当于链表中的节点。列表项的地址是非连续的&#xff0c;列表项的数量可随时修改。在OS中的任务状态和数量会发生改变&#xff0c;因此使用列表可以很好的满足需求。 列表和列表项的相关定义与操作函…

电商独立站||跨境电商独立站网站搭建|功能系统搭建||API接口接入

搭建多语言跨境电商独立站系统 前台主要功能模块 短信接口 第三方登陆 支付方式 会员中心 代购订单列表 - new 会员签到 -1000(1) new 支付密码 ---1000 国内流程 -----5000 new 订单运单多退少补 -1000 未付款运单取消功能 - 修改运单运输方式 -----1000 年费会员 -----3000 …

D435+opencv识别色块

在当前的机器视觉和机器人技术领域&#xff0c;实时图像处理是一项至关重要的技术。本文介绍了如何利用Python、OpenCV库以及Intel的Realsense摄像头来进行实时的颜色识别。这种技术可以广泛应用于自动化检测、机器人导航以及交互式媒体等领域。 一、 开发环境配置 首先&#x…

大型零售企业,适合什么样的企业邮箱大文件解决方案?

大型零售企业通常指的是在全球或特定地区内具有显著市场影响力和知名度的零售商。这些企业不仅在零售业务收入上达到了惊人的规模&#xff0c;而且在全球范围内拥有广泛的销售网络和实体店铺。它们在快速变化的零售行业中持续创新&#xff0c;通过实体店、电商平台等多种渠道吸…

C#队列(Queue)的基本使用

概述 在编程中&#xff0c;队列&#xff08;Queue&#xff09;是一种常见的数据结构&#xff0c;它遵循FIFO&#xff08;先进先出&#xff09;的原则。在C#中&#xff0c;.NET Framework提供了Queue<T>类&#xff0c;它位于System.Collections.Generic命名空间下&#x…

【深度学习实战(26)】标签处理之语义分割标签转换,数据集划分

一、标签转换 我们在使用labeme标签工具&#xff0c;标注完数据后会获得json文件。在标注结束过后&#xff0c;我们需要通过标签转换操作&#xff0c;生成jpg格式原始图片和png格式mask标签图。 1.1 使用img_b64_to_arr将json标签中二进制图像数据变成numpy格式数据&#xf…

介绍一个小技巧-Luhn算法

这种算法主要用于验证身份识别码的正确性&#xff0c;比如信用卡号、发卡行识别码、国际移动设备识别码&#xff08;IMEI&#xff09;、美国国家提供商标识号码以及电子票的票号验证等。是由IBM科学家Hans Peter Luhn于1954年发明的一种简单校验和算法。在工业自动化领域也有使…

selenium在Pycharm中结合python的基本使用、交互、无界面访问

下载 下载与浏览器匹配的浏览器驱动文件&#xff0c;这里一定注意的是&#xff0c;要选择和浏览器版本号相同的驱动程序&#xff0c;否则后面会有很多问题。 &#xff08;1&#xff09;浏览器&#xff08;以google为例&#xff09;版本号的查询&#xff1a; 我这里的版本号是1…