动态规划---斐波那契数列模型

目录

一、斐波那契数列的基本概念

二、动态规划在斐波那契数列中的应用与优势

三、实际案例:使用动态规划解决斐波那契数列问题

四、动态规划问题的做题步骤

五、例题

1、第N个泰波那契数---点击跳转题目

2、三步问题----点击跳转题目

3、最小花费爬楼梯----点击跳转题目

4、解码方法----点击跳转题目


本文通过对斐波那契数列问题引入动态规划,这也是动态规划问题中比较简单的一类问题,通过这个模型我们一起来学习什么是动态规划算法并且动态规划问题的基本做题步骤是什么

一、斐波那契数列的基本概念

斐波那契数列是这样一个数列:从第三项开始,每一项都等于前两项之和。数列的前几项为:0, 1, 1, 2, 3, 5, 8, 13, 21, ...。这个数列的特性使得它在很多实际问题中都有着重要的应用。

二、动态规划在斐波那契数列中的应用与优势

在计算斐波那契数列时,我们可以使用递归的方式。然而,递归方式在计算较大的斐波那契数时,会存在大量的重复计算,效率非常低。而动态规划技术可以有效地避免这种重复计算,显著提高计算效率。

动态规划的基本思想是将问题分解为若干个子问题,并将这些子问题的解保存起来,以便在计算新的子问题时能够直接利用之前的结果,避免重复计算。在斐波那契数列问题中,我们可以使用动态规划技术,从下往上计算斐波那契数列,并将每个计算结果保存起来,这样在计算较大的斐波那契数时,就可以直接使用之前保存的结果,通过空间换时间的操作,大大提高了计算效率。

三、实际案例:使用动态规划解决斐波那契数列问题

下面是一个C++代码示例,展示了如何使用动态规划来计算斐波那契数列:

#include<iostream>const int N = 100;
int dp[N];int main()
{dp[0] = 1,dp[1] = 1;int n;cin>>n;for(int i=2;i<=n;i++)dp[i] = dp[i-1] + dp[i-1];cout<<dp[n]<<endl;return 0;
}

在上述代码中,我们创建了一个列表dp来保存斐波那契数列的值。初始时,列表的前两个元素被设置为斐波那契数列的前两项。然后,我们通过一个循环,从第三项开始,依次计算斐波那契数列的每一项,并将结果保存在dp列表中。最后,返回dp[n],即第n项斐波那契数的值。

动态规划在斐波那契数列中的核心思想是通过保存子问题的解来避免重复计算。具体方法是将问题分解为子问题,并按照某种顺序(如上述示例中的从下往上)依次解决这些子问题,同时保存每个子问题的解。在计算新的子问题时,如果其解已经保存,则直接利用保存的解,否则通过解决更小的子问题来得到其解,并将解保存起来。

四、动态规划问题的做题步骤

在分析题目时分为五步:

  • 状态表示:根据 经验 + 题目要求 得出

dp[i]代表什么? 一般可以 以i为结尾 以i为起点 做状态表示

  • 状态转移方程:根据dp[i]的最近一步推导得出关于dp[i]的递推公式
  • 初始化:根据递推公式来初始化需要先用到的dp值
  • 填表顺序:根据递推公式来判断填表顺序
  • 返回值:题目要求

在编写代码时分为四步:

  • 创建dp表
  • 初始化
  • 填表
  • 返回值

五、例题

1、第N个泰波那契数---点击跳转题目

本题很简单明了,题目里面就已经给出了状态转移方程,由此,我们定义dp[n]是第n个泰波斐契数

代码:

class Solution {
public:int m = 40;int tribonacci(int n) {//空间优化if(n == 0) return 0;if(n == 1 || n == 2) return 1;int a = 0,b = 1, c = 1,d;for(int i=3;i<=n;i++){d = a + b + c;//滚动操作a = b; b = c; c = d;}return d;}
};

由于每个数只会用到它的前三个数,所以我们可以使用滚动数组来进行空间优化

2、三步问题----点击跳转题目

分析:

  • 状态表示:以i为结尾分析,dp[i]为到第i个台阶的方法总数
  • 状态转移方程:分析最近一步,由于一次可以跨1到3个台阶,所以到第i个台阶的最近一步就是先到i-1、i-2、i-3这三个台阶,再分别跨1、2、3个台阶到达第i个台阶,那么从i-1层到i层这种方式到i层的方法数就是到i-1层的方法数,以此类推:dp[i] = dp[i-1]+dp[i-2]+dp[i-3]; 可以看出递推公式和上一题一摸一样,只不过这个需要我们根据题意和经验自己推导。
  • 初始化:把上1、2、3层的台阶方法数先初始化,因为递推公式要用到三个数,根据题意,dp[1] = 1,dp[2] = 2,dp[3] = 4;
  • 填表顺序:由于递推公式是由小推大,所以从左向右填表
  • 返回值:根据题意,返回dp[n] 对1000000007取模的结果即可

代码:

class Solution {
public:int waysToStep(int n) {int MOD = 1e9 + 7;//创建dp表vector<int> dp(10+n);//初始化dp[1] = 1;dp[2] = 2;dp[3] = 4;//填表for(int i=4;i<=n;i++)dp[i] = ((dp[i-1]+dp[i-2])%MOD+dp[i-3])%MOD;//返回值return dp[n];}
};

题意是结果取模即可,但是因为数值过大,计算过程中就会爆数据范围,所以只能每做一次加法取一次模,和对结果取模等价; 注意,取模运算具有分配律:(A+B)%C = A%C + B%C

3、最小花费爬楼梯----点击跳转题目

分析:题中表示,从第i层向上爬,需要花费cost[i]的体力值,可以从0、1层向上爬,也就死选择到0/1层并不花费体力值;

  • 状态表示:以i为结尾,dp[i]:到第i层花费的最小体力值
  • 状态转移方程:由dp[i]最近一步推导,由于一次可以爬1~2步,到第i层之前,要么在i-1层,要么在i-2层,分类讨论,从i-1层到i层的最小花费为:dp[i-1]+cost[i-1];从i-2层到i层的最小花费为:dp[i-2]+cost[i-2],一共这两种情况,哪一种才是到达i层的最小花费呢?两者取个最小值即可:dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2])
  • 初始化:由递推公式可知需要前两个dp值,由题意,选择上0或1层台阶不花费体力值,dp[0] = dp[1] = 0
  • 填表顺序:由递推公式是在小推大,所以我们从左向右填表
  • 返回值:根据题意,返回dp[n]就是到达第n层台阶的最小花费

代码:

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size();vector<int> dp(10+n);dp[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];}
};

看到这里,可能有读者会有疑惑,分析状态表示时这三个题怎么都是以i为结尾分析,做题步骤中不是还有以i为起点分析吗?其实都可以,做题的时候觉得怎样更方便就选择怎样,那么这道题我们也以i为起点来举例分析一下

  • 状态表示:以i为起点,dp[i]表示以i为起点到楼顶的最小花费
  • 状态转移方程:分析dp[i]最近的一步,以i为起点,自然只能向后看,最近的一步就是i+1层台阶和i+2层台阶; dp[i] = cost[i] + min(dp[i+1],dp[i+2])
  • 初始化:由递推公式可知,是要先直到后面的值推导前面的值,dp[n] = 0, dp[n-1] = cost[i-1]
  • 填表顺序:由递推公式,是大推小,所以是从右往左填表
  • 返回值:根据题意,要求的是从0层或1层到n层的最小花费,所以结果为min(dp[0],dp[1])

代码:

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {   //dp[i]:以i位置出发到达楼顶的最小花费//dp[i] = min(dp[i+1]+cost[i],dp[i+2]+cost[i]);int n = cost.size();vector<int> dp(n+10);dp[n] = 0;dp[n-1] = cost[n-1];for(int i=n-2;i>=0;i--)dp[i] = cost[i] + min(dp[i+1],dp[i+2]);return min(dp[0],dp[1]);}
};

这道题怎么分析都可以,建议两种视角都看一遍加深理解

4、解码方法----点击跳转题目

分析:一个字符要么单独解码,要么合并另一个字符解码,合并时前导0情况表示解码失败

  • 状态表示:以i为结尾,dp[i]表示以i为结尾时的解码方法总数
  • 状态转移方程:根据dp[i]最近的一步,就是以i位置的字符单独解码或者i和i-1的字符合并解码两种情况,其中每种情况都要判断其合法性,是否能解码成功,解码失败则表示i位置这种情况下的解码方法数是0,如果两种情况都解码成功,dp[i] = dp[i-1] + dp[i-2]

  • 初始化:初始化0,1即可,根据是否能解码成功来分类

  • 填表顺序:从左往右
  • 返回值:dp[s.size()]

代码:

class Solution {
public:int numDecodings(string s) {int n = s.size();vector<int> dp(10+n);if(s[0]-'0' != 0) dp[0] = 1;else dp[0] = 0;if(s[0]-'0' && s[1]-'0') dp[1]++;int t = (s[0]-'0')*10 + s[1] - '0';if(t>=10 && t<= 26) dp[1]++;for(int i=2;i<n;i++){if(s[i] != '0') dp[i] += dp[i-1];int t = (s[i-1] - '0')*10 + s[i] - '0';if(10<=t && t<=26) dp[i] += dp[i-2];}return dp[n-1];}
};

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

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

相关文章

FANUC机器人socket通讯硬件配置

一、添加机器人选配包 Fanuc机器人要进行socket通讯&#xff0c;需要有机器人通讯的选配包&#xff0c;1A05B-2600-R648 User Socket Msg&#xff0c;1A05B-2600-R632 KAREL&#xff0c;1A05B-2600-R566 KAREL Diagnostic&#xff0c;1A05B-2600-J971 KAREL Use Sprt FCTN。 二…

【漏洞复现】WebLogic XMLDecoder反序列化(CVE-2017-10271)

1、漏洞描述 CVE-2017-10271漏洞产生的原因大致是Weblogic的WLS Security组件对外提供webservice服务&#xff0c;其中使用了XMLDecoder来解析用户传入的XML数据&#xff0c;在解析的过程中出现反序列化漏洞&#xff0c;导致可执行任意命令。攻击者发送精心构造的xml数据甚至能…

SpringMvc中的异常处理器(在SpringBoot中也可使用)

目录 一、单个控制器异常处理 二、全局异常处理器 三、自定义异常处理器 在开发过程中&#xff0c;Dao&#xff0c;service&#xff0c;Controller层代码出现异常都可能抛出异常。如果哪里产生异常就在哪里处理异常&#xff0c;则会降低开发效率。所以一般情况下我们会让异常…

clickhouse数据去重函数介绍(count distinct)

非精确去重函数&#xff1a;uniq、uniqHLL12、uniqCombined 精确去重函数&#xff1a;uniqExact、groupBitmap 测试数据量&#xff1a;2000w 结论&#xff1a; 1.整形值精确去重场景&#xff0c;groupBitmap 比 uniqExact至少快 2x 2.groupBitmap仅支持无符号整形值去重&#x…

文化旅游3D数字孪生可视化管理平台推动文旅产业迈向更加美好的未来

随着数字化、智能化管理成为文旅产业发展的必然趋势&#xff0c;数字孪生公司深圳华锐视点创新性地推出了景区三维可视化数字孪生平台&#xff0c;将线下的实体景区与线上的虚拟世界完美融合&#xff0c;引领智慧文旅新潮流。 我们运用先进的数字孪生、web3D开发和三维可视化等…

【Bug记录】@RequestBody参数属性为空的问题

1、问题发生背景 使用postman调用之前测试成功的接口&#xff0c;再进行项目拆分&#xff0c;重构之后&#xff0c;接口突然不通了&#xff0c;排查了很久&#xff0c;以为是框架调整&#xff0c;导致出了问题。 2、问题发生的原因 经过一系列的排查&#xff0c;排查详细过程就…

linux内核网络源码-用户空间与内核的接口

内核通过各种不同的接口把内部信息输出到用户空间&#xff0c;除了程序员用于请求特定信息的经典系统调用外&#xff0c;还有三个特殊接口&#xff0c;而其中两个是虚拟文件系统&#xff1a; procfs 文件系统 这是一个虚拟文件系统&#xff0c;通过是挂在proc ,允许内核以文件的…

详解Qt中的鼠标事件

在Qt中&#xff0c;处理鼠标事件是构建交互式界面的关键。Qt提供了一系列与鼠标相关的事件处理函数&#xff0c;允许开发者捕获鼠标的各种动作&#xff0c;如按下、释放、移动、双击等。以下是鼠标事件的使用方法、技巧以及注意事项&#xff0c;并附带C代码示例。 基础使用方法…

GDB多线程调试:Redis的IO多线程

Redis采用的网络模型是单线程的Reactor网络模型&#xff0c;异步处理&#xff0c;因为性能很高。 Reactor先从客户端获取请求&#xff0c;然后dispatch给具体的执行的线程。处理的流程即为read->decode->compute->encode->send。 而Redis的IO多线程的处理时&…

【C++】:拷贝构造函数和赋值运算符重载

目录 一&#xff0c;拷贝构造函数1. 什么是拷贝构造函数2. 拷贝构造函数的特性3. 实践总结 二&#xff0c;赋值运算符重载2.1 运算符重载2.2 赋值运算符重载 一&#xff0c;拷贝构造函数 1. 什么是拷贝构造函数 拷贝构造函数是特殊的构造函数。是用一个已经存在的对象&#x…

什么是哈希表

为了解力扣第一题自学哈希表&#xff0c;做总结。 哈希函数的原理&#xff1a; 如果输入一个参数&#xff0c;那么哈希函数就会输出一个数字&#xff0c;并且不同的输入会有不同的输出&#xff0c;相同的输入会有相同的输出。例如&#xff1a; 苹果————89 苹果————…

SAP采购订单-条件类型-配置开发步骤

由于采购业务变更&#xff0c;需要创建新的价格类型&#xff0c;并添加新的计算逻辑计算。首先在例程&#xff08;VOFM&#xff09;中创建计算逻辑&#xff0c;然后在系统配置&#xff08;SPRO&#xff09;中找到配置点&#xff0c;创建新的条件类型‘ZMM00’,创建定价过程‘ZM…

SpringCloud系列(16)--将服务提供者Provider注册进Zookeeper

前言&#xff1a;在上一章节中我们说明了一些关于Eureka自我保护模式&#xff0c;而且自上一章节起关于Eureka的知识已经讲的差不多了&#xff0c;不过因为Eureka已经停更了&#xff0c;为了安全考虑&#xff0c;我们要用还在更新维护的注册中心来取代Eureka&#xff0c;而本章…

Flink面试(2)

Flink面试&#xff08;1&#xff09;-CSDN博客 9. Flink 状态如何存储&#xff1f; 在 Flink 中&#xff0c;状态存储 被叫做 StateBackend&#xff0c;它具备两种能力&#xff1a; 在计算过程中提供访问 State 能力&#xff0c;开发者在编写业务逻辑中能够使用 StateBacken…

Python IO流

1.什么是IO&#xff1f; IO&#xff08;输入/输出&#xff09;是计算机程序与外部世界进行数据交换的一种方式。在Python中&#xff0c;IO操作通常涉及文件、网络、标准输入和输出等。Python的IO操作可以分为两种类型&#xff1a;文本IO和二进制IO。 文本IO&#xff1a;用于读…

网络数据包嗅探器工具

组织的网络非常庞大&#xff0c;包含服务器、交换机、路由器和接入点等众多节点&#xff0c;由于许多资源和流量不断通过这些节点&#xff0c;因此很难确定大量流量是真实的还是安全攻击的迹象&#xff0c;了解和了解组织的网络流量至关重要&#xff0c;一个有用的资源是网络数…

MySQL--mysql的安装(压缩包安装保姆级教程)

官网下载&#xff1a;www.mysql.com MySQL :: Download MySQL Community Server (Archived Versions) 1.MySQL下载流程&#xff1a; 第一步&#xff1a;点击download&#xff0c; 下滑找到MySQL community&#xff08;gpl&#xff09;Downloads>> 第二步&#xff1a;点…

通俗易懂,十分钟让你了解并上手 Docker

通俗易懂&#xff0c;十分钟让你了解并上手 Docker 一、Docker 能拿来解决什么问题二、Docker 的概念与模型1. 容器化技术2. 镜像的概念3. Docker与虚拟机 三. Docker的使用1. 环境安装2. 制作镜像3. 镜像管理&#xff08;1&#xff09; 图形界面&#xff08;2&#xff09; 命令…

MySQL 8.0性能优化实战培训

课程介绍 【云贝独家】MySQL 性能优化进阶课程&#xff0c;引领你的职业巅峰&#xff01; 同学们&#xff0c;你们是否被各种工作中的性能问题困扰&#xff1f;是否渴望提升自己在MySQL数据库方面的技术能力&#xff0c;掌握最新最前沿的技术知识呢&#xff1f; 我们讲师为你带…

深度学习中的黑科技:自监督学习(Self-Supervised Learning)

在人工智能领域&#xff0c;深度学习已成为推动技术革新的核心力量。然而&#xff0c;深度学习的一个重要瓶颈是对大量标记数据的依赖性。在这个背景下&#xff0c;自监督学习(Self-Supervised Learning, SSL)作为一种新兴的学习范式&#xff0c;越来越受到研究者的关注。自监督…