动态规划(DP)算法初识
先用大白话来说一下几种经典算法大概的意思:
- 贪心算法:我就一次机会,为了达到目的,其他的我啥也不考虑
- 回溯算法:我有无数次机会,还能怕我有达不到目的的时候?
- 动态规划算法:我能随意在任何时候进行存档读档,用最华丽的方法走到终点。
接下来的几篇文章可能都会围绕dp来说,从白话和较多篇幅去解释dp算法的内在
简述
动态规划求解出最优策略的原理是因为显著的降低了时间复杂度,提高了代码的运行效率,但动态规划也确实很难学,不过,一旦我们知道了解决思路,那么对于很多动态规划的问题,也都可以用相似的思路去解决。
将会用实际的问题,更好的去去理解动态规划
0-1 背包问题
在上一期的回溯的相关算法中,我们知道了如何采用递归的思想穷举所有解法,选出最优,然后解决问题,还是这道题,如果我们要对于一组不同重量、不可分割的物品,选择一些装入背包,在满足最大重量限制的前提下,如何最贴近最大重量。
我们首先用递归树看一下回溯的思路:
首先假设每个物品重量是 2 2 4 6 3,我们假设 i 表示将要决策第几个物品是否装入背包,cw表示当前背包中物品的总重量,然后用(i,cw)。比如,(2,2)表示将要决策第2个物品是否要装入背包,决策前,背包的总重为2.
我们可以从递归树明显的看出,有些子问题的求解是重复的,重复的计算必然会造成性能的丢失,如果我们能保留之前的结果,计算之前先检索一下,如果有计算过,那么直接拿过来用,肯定会提升一下性能。
事实上,动态规划的思路已经和这相差无几,但还是让我们来看看动态规划的思路:
- 首先将整体求解分为n个阶段,每个阶段会决策一个物品是否放到包里。
- 不论放入还是不放入,背包的重量假设都造成了变化,而这些不同的变化,也就对应着递归树的节点
- 合并重复的节点,避免节点指数级增长
- 基于这一层的节点,推导出下一层的状态集合
然后用上面的思路,代入到0-1背包问题中做一个思路引导:
- 首先我们创建一个布尔类型的二维数组states[n][w],记录每个节点的不同状态。n代表第n个物品,w代表背包能承受的最大质量。
- 第0个(假设物品序列从0开始计算)物品的重量是2,放入,就是states[0][2],不放入,就是states[0][0],但是因为最大重量w是9,所以上面两个表达式的结果都是true。
- 然后是第一个物品,重量也是2,那么造成的结果就是,states[1][4],states[1][2],states[1][2],states[1][0]
- 然后我们发现,有两个表达式重复了,所以合并掉,其他三个因为重量小于9,所以也是true
- 不断继续,最后只需要选择最接近9还是true的就行了。
用false代表0,用true代表1,效果图如下:
然后再用代码表达一下:
这就是动态规划总体的思路,而且时间复杂度比起回溯的n²也有了很大的改善,为wn,n表示物品个数,而w表示可以承载的总重。
但是为了能够解决所有的情况,我们在存档的时候还是很占用空间的,那么有什么办法降低空间消耗吗?
实际上,我们可以将二维数组转换成一维数组,在动态转移的过程中都可以依靠这个一维数组来完成,下面来展示一下代码:
0-1背包问题升级版
如果我们再将这些物品赋予价值概念的话,该如何让背包最大可承受重量一定的时候让价值更高。
首先,这个问题也是可以通过回溯的办法解决的:
还是针对上面的代码画出递归树,和之前的思路相同,只不过加入了一个新的值:value
我们发现,在很多情况下,重量相同但是价值会有区别,这也就是我们这个题目的目标,舍弃掉相对价值低的,保留相对价值更高的,保留递归的思路,其他状态就不考虑了。
于是我们继续采用动态规划思想。
设一个二维数组states[n][w+1],来记录每层都可以达到的不同状态,不过这次不再是布尔类型了,而是int类型,用来记录当前状态的最大价值。然后按照之前的思路,根据当前阶段,推导出后续状态。
然后翻译成代码:
其实思路都是和之前相同的,但是在这里引入了第三个变量,也就是value,和之前的例子大同小异,时间复杂度也仍然是wn。
动态规划(DP)算法初识相关推荐
- 动态规划算法python_动态规划——DP算法(Dynamic Programing)
一.斐波那契数列(递归VS动态规划) 1.斐波那契数列--递归实现(python语言)--自顶向下 递归调用是非常耗费内存的,程序虽然简洁可是算法复杂度为O(2^n),当n很大时,程序运行很慢,甚至内 ...
- 动态规划DP算法理解
1. DP算法定义: 每次决策依赖于当前状态,又随即引起状态的转移,多阶段最优化决策解决问题的过程就称为动态规划. 2. DP算法基本流程: 初始状态→│决策1│→│决策2│→-→│决策n│→结束状态 ...
- c语言dp算法,C++动态规划dp算法题
问题1:找硬币,换钱的方法 输入: penny数组代表所有货币的面值,正数不重复 aim小于等于1000,代表要找的钱 输出: 换钱的方法总数 解法1:经典dp,空间复杂度O(n*aim) class ...
- 蓝桥杯备考-刷题之路-动态规划算法(DP算法)Part1
之前在刷力扣的时候就是浑浑噩噩的,照着评论区的答案写了一遍就万事大吉了,没有深度思考过.这次备考蓝桥杯看到DP算法的第一道题就不会,更难受的是看答案了依然完全不理解,所以决心把DP算法一次弄懂. 开始 ...
- dp笔记:关于DP算法和滚动数组优化的思考
从网上总结了一些dp的套路以及对滚动数组的一些思考,现记录如下,希望以后回顾此类算法时会有所帮助. 目录 1.DP算法经验 1.DP算法核心: 2.DP算法类别以及例题 例1:三步问题 例2:最小路径 ...
- 省选+NOI 第一部分 动态规划DP
期望概率DP [整理]简单的数学期望和概率DP [整理]简单的数学期望和概率DP - nimphy - 博客园 期望&概率dp总结 期望&概率dp总结_十分残念的博客-CSDN博客 期 ...
- 第十四周DP算法总结
这周自己主要再看DP算法的博客,感觉DP这一部分内容确实比之前的都要麻烦一些,最后攻克这一部分难题还是挺好的. 这周自己总结了一些题型,以及一些方法思路,最后再把动态规划和之前的分治和贪心做一下比较. ...
- 模式识别读书报告---关于DP算法的…
我喜欢玩星际争霸,当我操作我的部队用快捷键A进攻敌人时,部队就会自动避开障碍物attack目标.当时我就对为什么部队能自动选择最短的路进攻产生了兴趣,它是用什么算法实现的.而且当你的对手是电脑时,是用 ...
- 动态规划: dp+递推——确定动态矩阵dp含义,确定每个状态下面临的选择和对结果值影响,选择符合题意的作为结果存储在dp中
1.动态规划:每一个状态一定是由之前的状态推导出来的,通过总结归纳发现递推关系 2.解决动态规划问题的步骤: 确定dp数组(dp table)以及下标的含义: 每个单元内 题目所求的值,一维.二维 确 ...
- dpresult在python中什么意思_动态规划(DP)的整理-Python描述
今天整理了一下关于动态规划的内容,道理都知道,但是python来描述的方面参考较少,整理如下,希望对你有所帮助,实验代码均经过测试. 请先好好阅读如下内容--什么是动态规划? 摘录于<算法图解& ...
最新文章
- 修改路由表来使路由分流
- 问题1:程序员要做一辈子?
- PC微信逆向:分析发送xml名片call
- Hulu 2013北京地区校招笔试题
- Java 数组转化成集合
- Ajax方法实现登录页面
- Ubuntu 18.04 安装搜狗拼音 2022年版 Install sogou pinyin in Ubuntu 18.04 in 2022
- qcap 教程_高通平台抓取ramdump及使用qcap解析,ramdumpqcap
- (最完美)MIUI12系统的Usb调试模式在哪里开启的步骤
- Alfa: 1 vulnhub walkthrough
- STM32 SPI获取磁性角度传感器AS5048A角度数据
- statusbar 纯白色的解决方案 android:fitsSystemWindows
- Linux系统更改时区
- 【Java】Date日期类诠释
- Java:缓冲流、转换流、序列化流
- 对Redis中主从复制、哨兵模式和集群进行部署
- 创新实训(9)——SpringBoot整合solr
- java娘_初识java这个小姑娘(二)
- Android 《手机卫士》随听笔记
- c/c++中sizeof()、strlen()、length()、size()详解和区别