当前位置: 首页 > news >正文

我爱学算法之——动态规划(一)

前言

动态规划简单来说:是一种把大问题拆成可复用的小问题的算法思想,通过记录子问题的解避免重复计算,用状态转移方程递推得到最终答案,本质是空间换时间,常用于求最优解和方案数。

利用动态规划去解决问题,最重要的是:

  • 状态表示:明确 dp 数组中存的是什么(状态表示的是什么
  • 状态转移方程:找到当前答案和子问题答案的关系(如何计算

一、第 N 个泰波那契数

题目解析

泰波那契序列:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给定一个整数n,返回第 n 个泰波那契数。

算法思路

对于这道题,状态表示和状态转移方程 在题目当中已经给出来了:

初始化

在状态转移方程,求dp[i]时,用到了dp[i-1]dp[i-2]dp[i-3],所以就要初始化dp[0]、dp[1]、dp[2]

代码实现

classSolution{public:inttribonacci(intn){vector<int>dp(n+3,0);dp[0]=0;dp[1]=dp[2]=1;for(inti=3;i<=n;i++)dp[i]=dp[i-1]+dp[i-2]+dp[i-3];returndp[n];}};

对于这道题0<= n <= 37,n是可以为 0的,这里多开辟了3个数据的空间;即使n 为 0,也不会出现访问越界的情况。

二、三步问题

题目解析

有个小孩要上楼梯,他可以一次上 1阶、2阶、3阶。

现在有 n 阶台阶的楼梯,求小孩有多少种上楼梯的方式。

示例

n = 3,一共有4种走法:0-1-2-3、0-1-3、0-2-3、0-3

算法思路

状态表示

对于这道题,要记录的就是:上到第 n 阶台阶,有多少走法

dp[i]表示:上到第 i 阶台阶,走法的数量

状态转移方程

要上到第 i 阶台阶,可以从第 i-1、i-2、i-3 阶上到第 i 阶;所以到第 i 阶台阶的走法 就等于 到第i-1、i-2、i-3阶台阶走法的总和。

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

初始化

在状态转移方程中,求 dp[i] 时用到了 dp[i-1]、dp[i-2]、dp[i-3]

这里就需要初始化:dp[1]、dp[2]、dp[3](可以添加一个虚拟位置,这样初始化 dp[0]、dp[1]、dp[2]即可)

注意

在计算的过程当中,数据可能超过 int 的范围,所以计算过程当中就对其 % 1000000007。

代码实现

classSolution{public:intwaysToStep(intn){inttmp=1000000007;vector<int>dp(n+3,0);dp[0]=dp[1]=1;dp[2]=2;for(inti=3;i<=n;i++)dp[i]=((dp[i-1]+dp[i-2])%tmp+dp[i-3])%tmp;returndp[n];}};

三、使用最小花费爬楼梯

题目解析

给定一个数组 cost,其中 cost[i] 表示从 第 i 阶台阶向上爬需要支付的费用;一次可以向上爬一个或者两个台阶。

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

求 : 爬到楼梯顶部的最低花费(注意:这里顶部指的是下标 n 位置)

算法思路

状态表示: dp[i] 表示爬到第 i 阶台阶的最低花费

状态表示dp[i] = min(dp[i-1] + nums[i], dp[i-2] + nums[i-2]);

代码实现

classSolution{public:intminCostClimbingStairs(vector<int>&cost){intn=cost.size();vector<int>dp(n+2,0);for(inti=2;i<=n;i++){dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);}returndp[n];}};

四、解码方法

题目解析

字母A-Z依次对应 数字1-25

给定一个只含数字的字符串,计算并返回 解法方法的总数。

示例11106可以映射:AAJF1,1,10,6)、KJF(11,10,6);06不是一个合法的编码

算法思路

在确定状态表示时,可以根据题目描述和刷题经验来综合确定(例如:以 i 位置为结尾,…)

对于这道题,状态表示:dp[i] 表示 以 i 位置为结尾(区间[0,i])解码方法的总数

状态转移方程

状态转移方程,就思考 dp[i] 从何而来,如何去求

对于 i 位置,解码有两种情况:

所以,当s[i] != '0'时:

s[i] == '0'

初始化

在状态转移方程中,使用到了dp[i-1]dp[i-2],这里就需要初始化dp[0]dp[1]

如果s[0] == '0',dp[0] = 0;否则 dp[0] = 1

对于 dp[1],初识为 0

代码实现

classSolution{public:intnumDecodings(string s){intn=s.size();vector<int>dp(n+2,0);dp[0]=s[0]!='0';if(n==1)returndp[0];if(s[0]!='0'&&s[1]!='0')dp[1]++;inttmp=(s[0]-'0')*10+(s[1]-'0');if(tmp>=10&&tmp<=26)dp[1]++;for(inti=2;i<n;i++){if(s[i]!='0')dp[i]+=dp[i-1];inttmp=(s[i-1]-'0')*10+(s[i]-'0');if(tmp>=10&&tmp<=26)dp[i]+=dp[i-2];}returndp[n-1];}};dp[i]+=dp[i-1];inttmp=(s[i-1]-'0')*10+(s[i]-'0');if(tmp>=10&&tmp<=26)dp[i]+=dp[i-2];}returndp[n-1];}};

本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

http://www.jsqmd.com/news/551841/

相关文章:

  • 给嵌入式新手的ST7789驱动避坑指南:从SPI模式到RGB565显示的完整配置流程
  • Aspen Plus助力费托工艺尾气转化:从CO₂到合成气的奇妙之旅
  • 如何快速掌握SMU Debug Tool:AMD Ryzen性能调试终极指南
  • GMSL GUI实战:利用EOM眼图与Link Margin优化高速链路设计
  • 人大金仓KingBaseES数据库迁移实战:从SQLServer到国产数据库的避坑指南
  • 鸿蒙智能车实战:基于HI3861与QT的远程控制与数据可视化系统设计
  • 革新性游戏增强工具:植物大战僵尸智能辅助套件
  • 从零到一:STM32F407 HAL库定时器中断精准点亮LED(CubeMX实战)
  • KKS-HF_Patch:让《Koikatsu Sunshine》焕发全新光彩的三大核心功能
  • 循环队列的5个经典面试题解析(附C语言实现代码)
  • 新手入门指南:零基础使用快马AI生成你的第一张产区标准示意图
  • 手机上的3D视觉革命:拆解iPhone结构光与安卓TOF的AR应用差异
  • 免费音频转录神器oTranscribe:记者学者的终极效率工具
  • 【跟韩工学Ubuntu第7课】-第7章 日志管理:rsyslog、journald与logrotate-002篇
  • 2021 年 3 月青少年软编等考 C 语言三级真题解析
  • OpCore-Simplify:革新黑苹果EFI配置流程的智能解决方案
  • Cosmos-Reason1-7B模型微调实战:基于领域数据提升专业问答效果
  • qt项目如何打包成exe
  • Boson NetSim 11实战:手把手教你配置Cisco路由器实现三个子网互通(含完整命令集)
  • VCS调试实战:从Makefile配置到DVE波形查看,手把手搞定Verilog单步调试
  • B站评论区成分检测器:智能分析工具如何帮你秒懂用户行为?
  • 【实战解析】GD32 KEIL开发中SWD接口失效的三大修复方案与深度排查
  • WPS JS宏实战:5分钟搞定批量生成Code128条形码标签(附PDF导出技巧)
  • 网络设备开发避坑指南:MDIO接口时序详解与常见硬件设计陷阱
  • 别再只传静态图了!用OpenMV+串口实现简易视频流,打造你的桌面级监控系统
  • 【中等】最长公共子序列问题(Java)
  • ArcGIS重分类实战:手把手教你搞定SWAT模型土地利用数据库(附CNLUCC对照表)
  • Linux下C/C++程序高效调试工具指南
  • 运筹学考试急救包:重点概念速记与常见题型解析(含分支定界法详解)
  • Wiki.js日志管理实战:从数据追踪到安全防护的全方位指南