- 动规讲解基础讲解一——01背包(模板)
作为动态规划的基础,01背包的思想在许多动规问题中会经常出现,so,熟练的掌握01背包的思路是极其重要的;
第一想法是?
(1) 枚举?万能的枚举啊。但对于n件物品,每件都可以选择取或者不取,总的可能性有2n, n = 30就大约已经有10亿种可能了!枚举所有可能选择一种不超过背包承重并且价值最大的物品组合,枚举量太大了。
(2) 贪心? 嗯,有点意思。先选最贵重的物品?找个反例:
n = 3, m = 3
v = (2,2,3)
w = (1,2,3)
按照先选贵重物品的策略,会先选择价值为3的那个,并且背包装满了,但是如果我们选取前两个物品,总价值可以达到4。
可能你已经想到了,考虑“性价比”,先选取“性价比”高的。性价比怎么定义呢?用价值除以重量!先选取单位重量价值最大的物品试试?
再举个例子:
n = 3, m = 7
v = (2,3,4)
w = (3,4,5)
按我们的方法因为2/3 < 3/4 < 4 / 5,我们先选择第三件物品,但是选了它之后别的东西放不下了!总价值是4,但如果我们选择前两件物品可以拿到总价值5。可见这两种贪心法是不行的。如果你有别的贪心策略,也可以试试,万一成功了呢?
令f(i,j)表示选决定了前i件物品,重量恰好为j的时候能获得的最大价值。
假设我们已经知道了全部的f(i-1,*)的值,如何求f(i,*),换句话说我们有了状态表示还不够,如何求出递推式?
对f(i,j)如果我们不选取第i件物品,则显然f(i, j) = f(i – 1,j)
如果我们要选取第i件物品,那么前i – 1件物品必须要达到j - wi且价值最大。由我们对f的定义,有f(i,j) = f(i-1,j - wi) + vi, 那么我们究竟选不选第i件物品呢?只好看哪个大了值大了,所以由
f(i,j) = max(f(i – 1, j) , f(i-1,j - wi) + vi)
当然只有j>= wi的时候我们才有选择第i件物品的权力。
那么初值是什么呢?f(0,*),一件物品也不选的时候,显然重量只能是0,其他的重量都不存在,我们用负无穷来表示不可能,因为求的是最大价值嘛。
那么,我们整理一下我们的递推式子和初值:
至此我们的问题得到了解答。分析下复杂度,我们的f第一维显然只能
到n,第二维能到多大呢?最大也就是背包的容量,再大没意义,全是-∞了。那么我们的空尽复杂度是O(n * m),我们求这些值的时候,每个值最多只从之前求的两个值比较得到结果,所以时间复杂度也是O(n * m)。前面提到的枚举算法时间复杂度是O(2^n),虽然我们不能得出动态规划算法更快的结论,但通常认为m不太大。
优化?我们看一下这个递推式子核心就是f(i,j) = max(f(i – 1, j) , f(i-1,j - wi) + vi), 看一下f(i,*)只与f(i-1,*)相关,再仔细看看我们的第维j,只和更小的值相关,我们可以省掉一维i,然后倒着循环j,用旧的值更新新的值,这时f一部分是旧的值f(i-1,*),一部分是新的值f(i,*)。更具体地说小于j地是旧值,其余是新值。
核心伪代码:
f(0) = 0 f(1..m) = -∞ for i = 1 to n dofor j = m downto wi dof(j) = max(f(j), f(j - wi))endfor endfor
所求结果是max{f(0..m)}
注意我们循环j只到wi,因为再小的j会导致我们无法选择第i件物品,这时我们直接使用不用第i件物品的旧值就好啦。简单吧?
那么现在,时间复杂度时不变的,空间复杂度降低O(m)了。
们尝试换一种状态表示? 我们令f(i,j)表示决定了前i件物品,总重量不超过j时能获得的最大价值。仔细想想递推式是不变的,那么初值呢?如果初值不变,f就没变化了……i= 0时,总重量时0,又因为0不超过任何整数,所以根据定义初值是f(0,*) = 0
那么最终结果呢?根据定义,最终结果是f(n,m)而没有必要再一串数里取最大了。可见即使递推式相同,初值不同也会定义不同的函数,请不要忽略初值的作用啊。同样我们可以优化掉第一维。
核心伪代码:
初值f(0..m) = 0 for i = 1 to n dofor j = m downto wi dof(j) = max(f(j), f(j - wi))endfor endfor
所求结果是f(m)
再换一种状态表示?刚才讲了,我们有重量和价值两个指标,那么我们令f(i,j)是决定了前i件物品,总价值恰好是j时的最小重量,那么经过类似的分析,我们可以写出这样的初值和递推式:
{0(i=0∩j=0)
f(i,j)= {∞(i=0∩j>0)
{f(i−1,j)(i>0∪j<vi)
{max(f(i−1,j),f(i−1,j−wi)+vi)(i>0∪j>vi)
那结果是什么呢?
根据定义结果是max{x| f(n, x) <= m}, 同样我们可以优化掉一维的空间复杂度。那么时间复杂度是什么呢? O(n * sum(vi)) sum(vi)表示所有vi的和,也是第二维有意义的大小。
f(0,1.. sum(vi))) = 0
最终的结果也一样……还是要找到max{x| f(n, x) <= m}。
可见,动态规划问题状态表示十分灵活,不同的状态表示会有不同的解决方法。努力取发现吧!
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000) 第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
输出可以容纳的最大价值。
3 6 2 5 3 8 4 9
输出示例
14
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,w[10000],d[10000],m,f[13000]; int main() {cin>>n>>m;for(int i=1;i<=n;i++) cin>>w[i]>>d[i];for(int i=1;i<=n;i++)for(int j=m;j>=w[i];j--)f[j]=max(f[j],f[j-w[i]]+d[i]);cout<<f[m]; }
如果对你有所帮助,别忘了加好评哦;么么哒!!下次见!88
转载于:https://www.cnblogs.com/cangT-Tlan/p/6217934.html
- 动规讲解基础讲解一——01背包(模板)相关推荐
- 01背包模板、完全背包 and 多重背包
转载请注明出处:http://blog.csdn.net/u012860063 讲解链接:http://www.cppblog.com/tanky-woo/archive/2010/07/31/121 ...
- 01背包模板、全然背包 and 多重背包(模板)
转载请注明出处:http://blog.csdn.net/u012860063 贴一个自觉得解说不错的链接:http://www.cppblog.com/tanky-woo/archive/2010/ ...
- 【NOIP2006】【Luogu1060】开心的金明(01背包模板)
problem 有n个物品,价格为wi, 重要度为vi. 在代价不超过m的情况下,最大化wi*vi的值 n < 30, m < 3e4 solution Qwq,Wi*Vi是确定的. 所以 ...
- - 动规讲解基础讲解八——正整数分组
将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. 整数个数n<=100,所有整数的和<= ...
- 01背包 模板1 2 总结
物品质量 w[0] w[1] w[2] ....... w[n] 背包容量c T 物品价值 v[0] v[1] v[2] ...... ...
- AcWing 2. 01背包问题(01背包模板)
题目链接 https://www.acwing.com/problem/content/2/ 思路 对于每一个物品我们能做一个选择,选上它(前提是当前的剩余背包容量够),或者不选,那么我们只需要在这其 ...
- hdu2602 骨头收集者 01背包 模板题
Bone Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目
(二)01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目 //有N件物品和一个容量为V的背包.第i件物品的体积是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. ...
- 背包问题基础模型深度总结-文长慎入(01背包,完全背包,多重背包)
先等一下,字多预警,密集恐惧症慎入,喂,你,就是你,小板凳搬好了吗,站久了可是会腿酸的 无节操地王婆卖瓜一下, 本文 深度好文 目录 先扯两句 0-1背包 其它类似的状态定义 1 2 小结 3 记忆 ...
- 动态规划之背包问题——01背包
算法相关数据结构总结: 序号 数据结构 文章 1 动态规划 动态规划之背包问题--01背包 动态规划之背包问题--完全背包 动态规划之打家劫舍系列问题 动态规划之股票买卖系列问题 动态规划之子序列问题 ...
最新文章
- BZOJ2339: [HNOI2011]卡农(dp 容斥)
- 建立Windows Embedded Compact 7开发环境
- python 输出“Hello, world”
- VOFM、Copy Control与合并开票
- Oracle Q-quote delimiter Quote(q) 字符串原样输出
- c++协程2 (boost::coroutine)
- 分配的访问权限的展台应用:最佳做法
- ubuntu运行python ide_打造vim中的python IDE
- C++继承详解:共有(public)继承,私有(private)继承,保护(protected)继承
- go的优势--链表与结构体使用
- 远离“数据呆” 对业务的理解和思考永远高于分析技术的选择
- 信号之sleep函数
- 【机器学习】【计算机视觉】非常全面的图像数据集《Actions》
- 与成都的幸福行动家交流GTD
- 计算机科学与工程国际研讨会,2018年北京计算机科学与技术国际研讨会
- 惠普136nw打印机清零_惠普136nw打印机清零_HP惠普打印机清零大全
- Powermill数控编程培训,潇洒模具三步教您精通cnc数控编程
- cab文件介绍及制作方法 1
- html中数字的格式设置,fmt:formatNumber 标签 | 菜鸟教程
- 【有感】失去人性,失去很多;失去兽性,失去一切
热门文章
- html基础之select ,datalist与details的异同
- Linux 软件包管理器 rpm
- 读过的书,记录一下,不要忘记提高自己
- 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第1节 网络通信概述_4_IP地址...
- 信步漫谈之JDK—源码编译
- animation和keyframes
- 虚拟机centOs Linux与Windows之间的文件传输
- 异常:操作可能会破坏运行时稳定性
- uva11549Calculator Conundrum
- 测试Live Writer Beta2功能