动态规划从入门到精通-蓝桥杯

news2024/12/25 12:29:50

一、了解动态规划

1.简单来说动态规划是一种状态转移与递推

2.例题引入——最少硬币问题

有多个不同面值的硬币(任意面值);
数量不限;
输入金额S,输出最少硬币组合。
(回顾用贪心求解硬币问题。)

贪心法

  • 硬币面值1、2、5。支付13元,要求硬币数量最少。

  • 贪心法:

(1) 5元硬币,2个

(2) 2元硬币,1个

(3) 1元硬币,1个

  • 正确! 答案是:2枚5元硬币+1枚2元硬币+1枚1元硬币。


  • 硬币面值1、2、4、5、6。支付9元,要求硬币数量最少。

  • 贪心法:

(1) 6元硬币,1个

(2) 2元硬币,1个

(3) 1元硬币,1个

  • 错误! 答案是:1枚5元硬币+1枚4元硬币。


======>硬币问题的正解是动态规划


动态规划

给定1,5,10,25,50这5种面值的硬币;
数量不限;
输入金额S,输出最少硬币组合。
  • 首先定义数组Min[ ] 记录最少硬币数量。

  • 对输入的某个金额i,Min[i]是最少的硬币数量。

  • 1. 只考虑1元面值的硬币。

  • i=1元时,等价于:i=i-1 = 0元需要的硬币数量,加上1个1元硬币。

------>其中把Min[ ]叫做“状态”;把Min[ ]的变化叫做“状态转移”。

  • 2.所有金额仍然都只用1元硬币。

  • i=2元时,等价于:i=i-1 = 1元需要的硬币数量,加上1个1元硬币。

  • i=3元时,...

  • i=4元时,...

  • 3.在1元硬币的计算结果基础上,再考虑加上5元硬币的情况。从i=5开始就行了。

  • i=5元时,等价于:

(1) i = i-5 = 0元需要的硬币数量,加上1个5元硬币。Min[5]=1

(2) 原来的Min[5]=5。

取 (1) (2)的最小值,所以Min[5]=1。

  • i=6元时,等价于:

(1) i = i-5 = 1元需要的硬币数量,加上1个5元硬币。Min[6]=2

(2) 原来的Min[6]=6。

取 (1) (2)的最小值,所以Min[6]=2。

  • i=7元时,...

  • i=8元时,...


  • 动态规划总结

  • 用1元和5元硬币,结果:

  • 递推关系(状态转移方程):

Min[i] = min(Min[i], Min[i - 5] + 1)

继续处理其它面值硬币。

  • 动态规划实现代码(实现递推关系)

上面代码状态名是Min[ ],但是其实习惯上把状态命名为dp[ ]更好。

二、动态规划的两个特征

1.重叠子问题

子问题是原大问题的小版本,计算步骤完全一样;计算大问题的时候,需要多次重复计算小问题。

一个子问题的多次计算,耗费了大量时间。用DP处理重叠子问题,每个子问题只需要计算一次,从而避免了重复计算,这就是DP效率高的原因。

2.最优子结构

首先,大问题的最优解包含小问题的最优解。

其次,可以通过小问题的最优解推导出大问题的最优解。

三、记忆化

  • 如果各个子问题不是独立的,如果能够保存已经解决的子问题的答案,在需要的时候再找出已求得的答案,可以避免大量的重复计算。

  • 基本思路:用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。

四、动态规划求解过程图解

五、最经典的动态规划问题——0/1背包

给定n种物品和一个背包:
物品i的重量是wi,
其价值为Vi,
背包的容量为C。

背包问题: 
选择装入背包的物品,使得装入背包中物品的总价值最大。
如果在选择装入背包的物品时,对每种物品i只有两种选择:
装入背包或不装入背包,称为0/1背包问题。
  • 设xi表示物品i装入背包的情况:

xi=0,表示物品i没有被装入背包x;

i=1,表示物品i被装入背包。


有5个物品,重量分别是{2,2,6,5,4},
价值分别为{6,3,5,4,6},
背包的容量为10。

定义一个(n+1)X(C+1)的二维表dp[ ][ ]。
dp[i][i]表示把前i个物品装入容量为j的背包中获得的最大价值。
  • 填表:按只放第1个物品、只放前2个、只放前3个......一直到放完,这样的顺序考虑。(从小问题扩展到大问题)

  • 1、只装第1个物品。(横向是递增的背包容量)

  • 2、只装前2个物品

如果第2个物品重量比背包容量大,那么不能装第2个物品,情况和只装第1个一样。

如果第2个物品重量小于等于背包容量,那么:

  • (1)如果把物品2装进去(重量是2),那么相当于只把1装到(容量-2)的背包中。

需要用到前面的需要用到前面的结果,即已经解决的子问题的答案经解决的子问题的答案。

  • (2)如果不装2,那么相当于只把1装到背包中。

------>取(1) 和 (2)的最大值。

  • 3、只装前3个物品

如果第3个物品重量比背包容量大,那么不能装第3个物品,情况和只装第1、2个一样。

如果第3个物品重量小于等于背包容量,那么:

  • (1)如果把物品3装进去(重量是6),那么相当于只把1、2装到(容量-6)的背包中。

  • (2)如果不装3,那么相当于只把1、2装到背包中。

------>取(1) 和 (2)的最大值。


  • 按这样的规律一行行填表,直到结束。现在回头考虑,装了哪些物品。

  • 看最后一列,15>14,说明装了物品5,否则价值不会变化。

六、蓝桥杯真题(1174号)


1.DP状态设计

  • DP状态: 定义二维数组dp[ ][ ],大小为N * C。

  • dp[i][j]:把前i个物品(从第1个到第i个) 装入容量为j的背包中获得的最大价值。

  • 把每个dp[i][j]看成一个背包: 背包容量为j,装1~i这些物品。最后得到的dp[N][C]就是问题的答案:把N个物品装进容量C的背包的最大价值。

2.DP状态转移方程(递推公式)

  • 递推计算到dp[i][j],分2种情况:

  • (1)第i个物品的体积比容量j还大,不能装进容量的背包。那么直接继承前i-1个物品装进容量j的背包的情况即可: dp[i][j] = dp[i-1][j]。

  • (1)第i个物品的体积比容量j小,能装进背包。又可以分为2种情况: 装或者不装第i个。

  • 1)装第i个。从前i-1个物品的情况下推广而来,前i-1个物品是dp[i-1][j]。第i个物品装进背包后,背包容量减少c[i],价值增加w[i]。有:

dp[i][j] = dp[i-1][j-c[i]] + w[i]。

  • 2)不装第i个。那么:dp[i][j] = dp[i-1][j]。

  • 取1)和2)的最大值,状态转移方程:

dp[i][j] = max(dp[i- 1][j],d[i- 1][j- c[i]] + w[i])

3.代码

七、空间优化:滚动数组

  • 把dp[ ][ ]优化成一维的dp[ ],以节省空间。

  • Dp[i][]是从上面一行dp[i-1]算出来的,第i行只跟第i-1行有关系,跟更前面的行没有关系:

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + w[i])

  • 优化:只需要两行dp[0][]、dp[1][],用新的一行覆盖原来的一行,交替滚动。

  • 经过优化,空间复杂度从O(N*C)减少为O(C)

1.交替滚动

  • 定义:dp[2][i]: 用dp[O][]和dp[1][]交替滚动。

  • 优点:逻辑清晰、编码不易出错,建议初学者采用这个方法。

  • 代码:

  • now始终指向正在计算的最新的一行,old指向已计算过的旧的一行。

  • 对照原递推代码,now相当于i,old相当于i - 1

  • 对照:

  • 未经优化

  • 优化之后

2.自我滚动

  • 继续精简:用一个一维的dp[ ]就够了,自己滚动自己。

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + w[i])

  • 对照:

  • 未经优化

  • 优化之后

  • 注意:自我滚动时j从小往大循环是错误的

  • 优化之前填表的过程

  • 自我滚动填表的过程

  • 例如i = 2时,左图的dp[5]经计算得到dp[5] = 9,把dp[5]更新为9。

  • 右图中继续往后计算,当计算dp[8]时,得dp[8] = dp[5]’ + 3 = 9+3 = 12。

  • 这个答案是错的。

  • 错误的产生是滚动数组重复使用同一个空间引起的。

  • 注意:自我滚动时j从大往小循环是正确的

  • 优化之前填表的过程

  • 自我滚动填表的过程

  • 例如i = 2时,首先计算最后的dp[9] = 9,它不影响前面状态的计算。

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

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

相关文章

2023年中职网络安全竞赛跨站脚本渗透解析-2(超详细)

跨站脚本渗透 任务环境说明:需求环境可私信博主! 服务器场景:Server2126(关闭链接)服务器场景操作系统:未知访问服务器网站目录1,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问服务器网站目录2,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问…

CenterMask paper笔记

CenterMask是一个anchor free的实例分割模型, 来自paper: CenterMask: Real-Time Anchor-Free Instance Segmentation 提起anchor free, 会想到FCOS模型,是用来目标检测的, 那么这里就用到了FCOS, 不过换了backbone, 在FCOS检测出目标框后&…

插装式比例插装阀比例节流阀比例顺序阀放大器

都是直动式,不需要最小先导压力以及先导流量。它们的动作执行都是基于平衡力的设计理念。(电磁力能按比例地反作用于液压力)所有的比例螺线管都是按照5000psi(350bar)的标准设计,所以这些阀的所有口都可以承…

卷积网络与全连接网络的区别

问题卷积神经网络是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习。卷积神经网络具有表征学习能力,能够按其阶层结构对输入信息进行平移不变分类,因此也被称为“平移不变人工神经网络。全连接神经网络是具有多层感知器的的网络&a…

vs2022 实现无线调试安卓(Windows)

文章目录VS安装安卓调试环境前提条件Android SDK 版本查看安卓开启无线调试开启开发者模式打开USB调试功能打开无线调试功能查看配对信息(再次点击无限调试,不是switch开关)准备电脑端输入adb命令配对安卓查看设备清单如果没有设备VS无线调试…

python--matplotlib(3)

前言 Matplotlib画图工具的官网地址是 http://matplotlib.org/ Python环境下实现Matlab制图功能的第三方库,需要numpy库的支持,支持用户方便设计出二维、三维数据的图形显示,制作的图形达到出版级的标准。 其他matplotlib文章 python--matpl…

C++性能白皮书

最近看完了《C性能白皮书》,这本书列出了一些性能优化的思路,不过只是一些指引,没有讲具体细节,我整理出了其中的关键点分享给大家: 硬件篇 作为一个程序员,想要性能优化,最好要了解些硬件&…

关于JavaScript使用window.onload的解释说明

文章目录window.onload简介为什么使用window.onload()绑定有名的函数绑定执行多个函数window.onload 与 jQuery ready() 区别window.onload简介 window.onload() 方法用于在网页加载完毕后立刻执行的操作,即当 HTML 文档加载完毕后,立刻执行某个方法。 …

苹果手机怎么拦截垃圾短信,亲测有效的方法,图文教学

​当小伙伴的苹果手机频繁收到垃圾短信时,不仅会影响正常的日常生活,还有可能泄露个人信息,给小伙伴带来不必要的麻烦。苹果手机怎么拦截垃圾短信?本文小编将介绍苹果手机拦截垃圾短信的实用技巧,帮助你轻松应对垃圾短…

PPT怎么做都丑?试试这个自动化工具吧,酷炫报表的救星!

昨晚在网上冲浪的时候,看到某位字节员工在脉脉上发帖:31岁,被PPT弄丢了工作,理由是PPT做得太丑,配不上公司形象,建议人力评估,安排离职沟通。 其实看到这时,我并没有多大得感触。因…

Ceres的自动求导实现原理剖析

目录数学原理实现原理总结首先注意数值求导和自动求导在使用的时候的不同之处。 实际上,正是自动求导这个地方使用了类模板,导致它不仅可以传入参数,还可以传入Jet类型的数据,从而实现了参数的雅可比矩阵的计算,完成自…

centos7 搭建ELK(elasticsearch、logstash、kibana)

1、下载安装包 使用华为镜像站下载速度很快,华为镜像站:https://mirrors.huaweicloud.com/home,下载时需要保证版本一致 2、安装elasticsearch 解压到当前目录 [rootlocalhost elk]# tar zxvf elasticsearch-7.4.2-linux-x86_64.tar.gz 安…

RFID盘点软件为企业提供RFID固定资产管理方案

随着科技的发展,固定资产管理系统也经过了一些变革,从刚开始的单机版逐渐发展成SaaS版本,物联网版本等。从刚开始只支持条形码到支持二维码、RFID码。RFID固定资产管理系统上线后,通过给每个实物资产绑定一个RFID码标签后&#xf…

2022-06-16_555时基的迷人历史和先天缺陷!

https://www.eet-china.com/news/magazine220608.html 555时基的迷人历史和先天缺陷! 发布于2022-06-16 03:39:12 LARRY STABILE 流行数十年的555时基,业内不知晓的工程师应该寥寥无几!几乎所有的数字电路教材中,都有该芯片的身影…

华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】

使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12201821.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 分糖果 小明从糖果…

第六章.卷积神经网络(CNN)—CNN的实现(搭建手写数字识别的CNN)

第六章.卷积神经网络(CNN) 6.2 CNN的实现(搭建手写数字识别的CNN) 1.网络构成 2.代码实现 import pickle import matplotlib.pyplot as plt import numpy as np import sys, ossys.path.append(os.pardir)from dataset.mnist import load_mnist from collections import Order…

实时数仓Hologres新一代弹性计算组实例技术揭秘

作者:王奇(花名慧青) 阿里云Hologres研发 随着实时数仓在业务生产系统的普及,资源弹性、资源隔离等保障业务稳定性方面的技术需求开始变得越来越迫切。Hologres在保障业务方面持续优化核心技术竞争力,过去一年中&…

Facebook广告投放的正确姿势:玩转目标定位

如果你正在投放 Facebook广告,那么你一定有过这样的经历:明明设置了目标受众,但是广告却没有带来转化。在这方面,你可能忽略了一个很重要的因素——目标定位。想要打造高质量、高曝光率的 Facebook广告,如何才能成功实…

「TCG 规范解读」第7章 TPM工作组 TPM 总结

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…

90%的人都理解错了HTTP中GET与POST的区别

Get和Post是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二。 最直观的区别就是Get把参数包含在URL中,Post通过request body传递参数。 你可能自己写过无数个Get和Post请求,或者已经看过很多权威网站总结…