动态规划之爬楼梯模型

文章目录

  • 爬楼梯模型
    • LeetCode 746. 使用最小花费爬楼梯
      • 思路
      • Golang 代码
    • LeetCode 377. 组合总和 Ⅳ
      • 思路
      • Golang 代码
    • LeetCode 2466. 统计构造好字符串的方案数
      • 思路
      • Golang 代码
    • LeetCode 2266. 统计打字方案数
      • 思路
      • Golang 代码

爬楼梯模型

在这里插入图片描述
爬楼梯模型是动态规划当中的一个经典模型,可以抽象为:在当前这一步,你有若干个可选的操作,比如前进一步或前进两步,试问最少需要多少步能够到达终点。一个可能的变形是每一步具有固定的代价,试问到达终点的最小代价是多少。

最经典的爬楼梯问题就是初始时你处于第一层(第零级台阶),每次可以爬一个台阶或两个台阶,请问到达第 n 级台阶最少需要多少步。

依据这个最基本的爬楼梯模型,派生出了许多变体,参考灵茶山艾府整理的文档:分享丨【算法题单】动态规划(入门/背包/划分/状态机/区间/状压/数位/树形/优化),将这些题目的思路在此进行收录。

LeetCode 746. 使用最小花费爬楼梯

思路

可以看作是爬楼梯问题最简单的变体,在爬楼梯的过程中为每一步引入了代价,试问爬到终点最小的代价是多少。

使用 dp 数组记录的状态就是爬到当前这一级台阶的最小代价,由此可以推出状态转移方程:dp[i] = min(dp[i - 1] + cost[i - 1] + dp[i - 2] + cost[i - 2]),根据状态转移方程直接写代码即可。

Golang 代码

func minCostClimbingStairs(cost []int) int {n := len(cost)if n < 3 {return min(cost[0], cost[1])}dp := make([]int, n + 1)for i := 2; i <= n; i ++ {dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])}return dp[n]
}

LeetCode 377. 组合总和 Ⅳ

思路

可以将最终的 target 视为要攀爬的目标楼梯数,将 nums 数组当中的数字视为一次行动可以攀爬的楼梯数,这道题目可以抽象为一个爬楼梯问题。

具体来说,使用 dp 数组记录爬到某一层需要多少次行动,初始化 dp[0] = 1,作为动态规划的边界状态。状态转移方程可以写为: d p [ i ] = ∑ j = 0 n − 1 d p [ i − n u m s [ j ] dp[i] = \sum^{n-1}_{j=0}dp[i-nums[j] dp[i]=j=0n1dp[inums[j],前提是 i ≥ n u m s [ j ] i\geq nums[j] inums[j]

Golang 代码

func combinationSum4(nums []int, target int) int {n := len(nums)dp := make([]int, target + 1)dp[0] = 1for i := 1; i <= target; i ++ {for j := 0; j < n; j ++ {if i >= nums[j] {dp[i] += dp[i - nums[j]]}}}return dp[target]
}

LeetCode 2466. 统计构造好字符串的方案数

思路

从这一题开始,稍有难度。其实这道题本质上也是一个爬楼梯问题,zero 和 one 指的就是一次行动可以攀爬的楼梯数,只要爬上的台阶大于等于 low,就可以记录答案。

使用 dp 数组记录的是构造长度为 i 的字符串的方案数,只要 i 大于等于 low,那么dp[i]就是答案的一部分。

可以得到初步的状态转移方程:

dp[i]=dp[i-one]+dp[i-zero]

还需要考虑由于答案可能过大的取模情况,详见代码。

Golang 代码

func countGoodStrings(low int, high int, zero int, one int) int {dp := make([]int, high + 1)dp[0] = 1const MOD int = 1e9 + 7ans := 0for i := 1; i <= high; i ++ {if i >= zero {dp[i] = dp[i - zero] % MOD}if i >= one {dp[i] = (dp[i] + dp[i - one]) % MOD}if i >= low {ans = (ans + dp[i]) % MOD}}return ans
}

LeetCode 2266. 统计打字方案数

思路

这应该是灵神题单里最难的一道题,实际上也是一道爬楼梯问题。具体来说,根据不同数字的重复数,每一个号码能够构造出的字母方案可以被视为一个爬楼梯问题。比如对于数字 3,它对应的字符是“def”,如果按 1 次 3,那么只能构造出 d,如果按 2 次,可以构造出 dd 或 e,按 3 次,可以构造出 ddd/de/f/ed,使用 dp 来记录重复号码可能构造出的字符数,对于 7 和 9 之外的号码,状态转移方程是dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3],而对于 7 和 9 这两个有四个字符的号码,状态转移方程是dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3] + dp[i - 4]。预先将这两个 dp 数组处理出来即可。

每一次对一段重复的号码进行统计(最小的重复数是 1,也就是只按下一次这个按键),之后如果号码不再重复,就统计答案,这里要用到乘法原理,因为不同号码构造出的可能字符数的情况是互斥的。

Golang 代码

func countTexts(pressedKeys string) int {const MOD int = 1e9 + 7n := len(pressedKeys)dp3 := []int{1, 1, 2, 4}dp4 := []int{1, 1, 2, 4}for i := 4; i <= n; i ++ {dp3 = append(dp3, (dp3[i - 1] + dp3[i - 2] + dp3[i - 3]) % MOD)dp4 = append(dp4, (dp4[i - 1] + dp4[i - 2] + dp4[i - 3] + dp4[i - 4]) % MOD)}ans, cnt := 1, 1    // ans 记录最终的答案, cnt 记录当前字符的重复数for i := 1; i < n; i ++ {if pressedKeys[i] == pressedKeys[i - 1] {// 当前字符和前一个字符重复, cnt ++cnt ++} else {// 当前字符和前一个字符不重复, 此时要做的就是统计答案// 需要注意的是, 现在统计的是前一个字符的答案, 当前字符要在下一次 pressedKeys[i] != pressedKeys[i - 1] 的时候统计// 这就意味着 i == n - 1 的情况需要在这个 for loop 之后单独考虑if pressedKeys[i - 1] == '7' || pressedKeys[i - 1] == '9' {ans = ans * dp4[cnt] % MOD} else {ans = ans * dp3[cnt] % MOD}cnt = 1 // 重复的字符数重置为 1}}if pressedKeys[n - 1] == '7' || pressedKeys[n - 1] == '9' {ans = ans * dp4[cnt] % MOD} else {ans = ans * dp3[cnt] % MOD}return ans
}

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

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

相关文章

【每天一个知识点】湖仓一体(Data Lakehouse)

“湖仓一体”&#xff08;Data Lakehouse&#xff09;是一种融合了数据湖&#xff08;Data Lake&#xff09;与数据仓库&#xff08;Data Warehouse&#xff09;优势的新型数据架构。它既继承了数据湖对多类型数据的灵活存储能力&#xff0c;也具备数据仓库对结构化数据的高效查…

Linux | mdadm 创建软 RAID

注&#xff1a;本文为 “Linux mdadm RAID” 相关文章合辑。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文。 Linux 下用 mdadm 创建软 RAID 以及避坑 喵ฅ・&#xfecc;・ฅ Oct 31, 2023 前言 linux 下组软 raid 用 mdadm 命令&#xff0c;multi…

Unity自定义shader打包SpriteAtlas图集问题

Unity打包图集还是有一些坑的&#xff0c;至于图集SpriteAtlas是什么请参考我之前写的文章&#xff1a;【Sprite Atlas】Unity新图集系统SpriteAtlas超详细使用教程_spriteatlas 使用-CSDN博客 问题&#xff1a; 今天碰到的问题是&#xff0c;shader绘制的时候&#xff0c;因…

如何用 OceanBase 的 LOAD DATA 旁路导入进行大表迁移

前言 在日常工作中&#xff0c;我们时常会遇到需要将某个大数据量的单表进行迁移的情况。在MySQL中&#xff0c;针对这样的大表&#xff0c;我们通常会选择先将原表导出为csv格式&#xff0c;然后利用LOAD DATA语法来导入csv文件&#xff0c;这种方法相较于mysqldump在效率上有…

VR 互动实训的显著优势​

&#xff08;一&#xff09;沉浸式学习&#xff0c;提升培训效果​ 在 VR 互动实训中&#xff0c;员工不再是被动的知识接受者&#xff0c;而是主动的参与者。以销售培训为例&#xff0c;员工戴上 VR 设备&#xff0c;就能置身于逼真的销售场景中&#xff0c;与虚拟客户进行面对…

OpenCV 第6课 图像处理之几何变换(重映射)

1. 概述 简单来说,重映射就是把一副图像内的像素点按照规则映射到到另外一幅图像内的对应位置上去,形成一张新的图像。 因为原图像与目标图像的像素坐标不是一一对应的。一般情况下,我们通过重映射来表达每个像素的位置(x,y),像这样: g(x,y)=f(h(x,y)) 在这里g()是目标图…

Java虚拟机 - 程序计数器和虚拟机栈

运行时数据结构 Java运行时数据区程序计数器为什么需要程序计数器执行流程虚拟机栈虚拟机栈作用虚拟机栈核心结构运行机制 Java运行时数据区 首先介绍Java运行时数据之前&#xff0c;我们要了解&#xff0c;对于计算机来说&#xff0c;内存是非常重要的资源&#xff0c;因为内…

MySQL数据库——支持远程IP访问的设置方法总结

【系列专栏】&#xff1a;博主结合工作实践输出的&#xff0c;解决实际问题的专栏&#xff0c;朋友们看过来&#xff01; 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实…

CSS- 4.6 radiu、shadow、animation动画

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff01; 点…

排序算法之基础排序:冒泡,选择,插入排序详解

排序算法之基础排序&#xff1a;冒泡、选择、插入排序详解 前言一、冒泡排序&#xff08;Bubble Sort&#xff09;1.1 算法原理1.2 代码实现&#xff08;Python&#xff09;1.3 性能分析 二、选择排序&#xff08;Selection Sort&#xff09;2.1 算法原理2.2 代码实现&#xff…

第十节第一部分:常见的API:Math、System、Runtime

Math类介绍及常用方法&#xff08;了解知道即可&#xff09; System类介绍及常用方法&#xff08;了解知道即可&#xff09; Runtime类介绍及常用方法&#xff08;了解知道即可&#xff09; 代码&#xff1a; 代码一&#xff1a;Math类 package com.itheima.d14_math;public …

智能体间协作的“巴别塔困境“如何破解?解读Agent通信4大协议:MCP/ACP/A2A/ANP

AI 智能体的兴起触发了AI应用协作的新领域。这些智能体不再局限于被动的聊天机器人或独立的系统&#xff0c;它们现在被设计用于推理、计划和协作ーー跨任务、跨域甚至跨组织。但随着这一愿景成为现实&#xff0c;一个挑战很快浮出水面&#xff1a; 智能体如何以一种安全、可伸…

项目进度延误,如何按时交付?

项目进度延误可以通过加强计划管理、优化资源分配、强化团队沟通、设置关键里程碑和风险管理机制等方式来实现按时交付。加强计划管理、优化资源分配、强化团队沟通、设置关键里程碑、风险管理机制。其中&#xff0c;加强计划管理尤为关键&#xff0c;因为明确而详细的计划能提…

详解ip地址、子网掩码、网关、广播地址

1. IP 地址 定义&#xff1a;IP 地址是网络设备在网络中的唯一标识&#xff0c;用于标识设备的网络位置&#xff0c;类似于现实中的门牌号。它分为 IPv4&#xff08;如 192.168.1.5&#xff09;和 IPv6&#xff08;如 240e:305:3685:8100:a00:27ff:fefb:56b8&#xff09;。 示…

为 Windows 和 Ubuntu 中设定代理服务器的详细方法

有时下载大模型总是下载不出来&#xff0c;要配置代理才行 一、Windows代理设置 ① 系统全局代理设置 打开【设置】→【网络和Internet】→【代理】。 在【手动设置代理】下&#xff0c;打开开关&#xff0c;输入&#xff1a; 地址&#xff1a;10.10.10.215 端口&#xff1a;…

鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp

UniApp 实现的表单验证与提交功能 前言 在移动端应用开发中&#xff0c;表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便&#xff0c;还应该具备完善的验证与提交功能&#xff0c;以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证…

前端的面试笔记——HTMLJavaScript篇(二)前端页面性能检测

前端页面性能检测和判定是优化用户体验的核心环节&#xff0c;需要结合实验室数据&#xff08;Lab Data&#xff09;、现场数据&#xff08;Field Data&#xff09;和行业标准综合评估。以下是主流方法、工具及判定标准的详细解析&#xff1a; 一、性能检测的核心维度与指标 …

再来1章linux系列-19 防火墙 iptables 双网卡主机的内核 firewall-cmd firewalld的高级规则

学习目标&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 学习内容&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 1.实验 2.实验需求 图…

LLM-Based Agent综述及其框架学习(五)

文章目录 摘要Abstract1. 引言2. 文本输出3. 工具的使用3.1 理解工具3.2 学会使用工具3.3 制作自给自足的工具3.4 工具可以扩展LLM-Based Agent的行动空间3.5 总结 4. 具身动作5. 学习智能体框架5.1 CrewAI学习进度5.2 LangGraph学习进度5.3 MCP学习进度 参考总结 摘要 本文围绕…

游戏引擎学习第298天:改进排序键 - 第1部分

关于向玩家展示多个房间层所需的两种 Z 值 我们在前一天基本完成了为渲染系统引入分层 Z 值的工作&#xff0c;但还没有完全完成所有细节。我们开始引入图形渲染中的分层概念&#xff0c;即在 Z 轴方向上拥有多个独立图层&#xff0c;每个图层内部再使用一个单独的 Z 值来实现…