使用单调队列优化的 O(nm) 多重背包算法
我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接。
解析
多重背包的最原始的状态转移方程:
令 c[i] = min(num[i], j / v[i])
f[i][j] = max(f[i-1][j-k*v[i]] + k*w[i]) (1 <= k <= c[i]) 这里的 k 是指取第 i 种物品 k 件。
如果令 a = j / v[i] , b = j % v[i] 那么 j = a * v[i] + b.
这里用 k 表示的意义改变, k 表示取第 i 种物品的件数比 a 少几件。
那么 f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
可以发现,f[i-1][b+k*v[i]] - k*w[i] 只与 k 有关,而这个 k 是一段连续的。我们要做的就是求出 f[i-1][b+k*v[i]] - k*w[i] 在 k 取可行区间内时的最大值。
这就可以使用单调队列优化。
代码
其中 Q1 是一个用来存储可用状态的队列, Q2 是单调队列。
//f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
for (int i = 1; i <= n; ++i) {
Ni = Num[i]; Vi = V[i]; Wi = W[i];
for (int j = 0; j < Vi; ++j) {
Head1 = Tail1 = 0;
Head2 = Tail2 = 0;
Cnt = 0;
for (int k = j; k <= m; k += Vi) {
if (Tail1 - Head1 == Ni + 1) {
if (Q2[Head2 + 1] == Q1[Head1 + 1]) ++Head2;
++Head1;
}
t = f[k] - Cnt * Wi;
Q1[++Tail1] = t;
while (Head2 < Tail2 && Q2[Tail2] < t) --Tail2;
Q2[++Tail2] = t;
f[k] = Q2[Head2 + 1] + Cnt * Wi;
++Cnt;
}
}
}
例题:HDOJ - 1171
使用单调队列优化的 O(nm) 多重背包算法的更多相关文章
- 【POJ1276】Cash Machine(多重背包单调队列优化)
大神博客转载http://www.cppblog.com/MatoNo1/archive/2011/07/05/150231.aspx多重背包的单调队列初中就知道了但一直没(不会)写二进制优化初中就写 ...
- [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)
[BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...
- bzoj4182 Shopping 点分治+单调队列优化多重背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- Luogu 3423 [POI 2005]BAN-银行票据 (多重背包单调队列优化 + 方案打印)
题意: 给出 n 种纸币的面值以及数量,求最少使用多少张纸币能凑成 M 的面额. 细节: 好像是要输出方案,看来很是头疼啊. 分析: 多重背包,裸体??? 咳咳,好吧需要低调,状态就出来了: dp [ ...
- [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)
4182: Shopping Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 374 Solved: 130[Submit][Status][Disc ...
- POJ 1742 (单调队列优化多重背包+混合背包)
(点击此处查看原题) 题意分析 给你n种不同价值的硬币,价值为val[1],val[2]...val[n],每种价值的硬币有num[1],num[2]...num[n]个,问使用这n种硬币可以凑齐[1 ...
- bzoj1531[POI2005]Bank notes 单调队列优化dp
1531: [POI2005]Bank notes Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 559 Solved: 310[Submit][Sta ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
随机推荐
- Microsoft office word关闭英文输入首字母大写设置
1.概述: 在使用office word的时,经常出现输入一段不需首字母大写的英文时,通常敲击完回车时word会自动将首字母大写,需要重新将首字母修改成小写,这样操作很不方便.于是需要对这个功能进行一 ...
- PC机安装Qt以及QT交叉编译环境 分类: OpenCV ZedBoard shell ubuntu Eye_Detection 2014-11-08 18:57 246人阅读 评论(0) 收藏
PC: apt-get install qtcreator Qt Embedded for ZedBoard: 下载qt-everywhere-opensource-src-4.7.3.tar.gz, ...
- [每日一题] 11gOCP 1z0-052 :2013-09-1 RMAN-- repair failure........................................A20
转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/10859315 正确答案:D 一.模拟上题的错误: 1.删除4号文件 [oracle@myd ...
- PHP手机获取6为不反复验证码
//存数字数组 $code = array(); while(count($code) < 6){ //产生随机数1-9 $code[] = rand(1,9); //去除数组中的反复元素 ...
- 一个备份MySQL数据库的简单Shell脚本(转)
Shell脚本是我们写不同类型命令的一种脚本,这些命令在这一个文件中就可以执行.我们也可以逐一敲入命令手动执行.如果我们要使用shell脚本就必须在一开始把这些命令写到一个文本文件中,以后就可以随意反 ...
- BZOJ 2525 Poi2011 Dynamite 二分答案+树形贪心
题目大意:给定一棵树,有一些点是关键点,要求选择不超过mm个点.使得全部关键点到近期的选择的点距离最大值最小 二分答案,问题转化为: 给定一棵树,有一些点是关键点,要求选择最少的点使得每一个关键点到选 ...
- IOS-UIProgressView的简单介绍
IOS-UIProgressView的简单介绍 转载:http://blog.sina.com.cn/s/blog_9c2363ad0101e1jy.html // UIProgressView的使用 ...
- IOS-tableViewCell重用机制
IOS-tableViewCell重用机制 首先介绍tableViewCell原生cell的使用和重用机制 使用dequeueReusableCellWithIdentifier方法,这个方法会从缓存 ...
- myeclipse配置svn亲测
1.安装目录更改为myeclipse install 目录:E:\MyEclipse85\MyEclipse 8.5common 目录: E:\MyEclipse85\Common ...
- Java基础知识强化之集合框架笔记30:集合之泛型的引入
1. 泛型的引入: (1)首先我们看看下面这一段代码,如下: package cn.itcast_01; import java.util.ArrayList; import java.util.It ...