我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接。

解析

多重背包的最原始的状态转移方程:

令 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) 多重背包算法的更多相关文章

  1. 【POJ1276】Cash Machine(多重背包单调队列优化)

    大神博客转载http://www.cppblog.com/MatoNo1/archive/2011/07/05/150231.aspx多重背包的单调队列初中就知道了但一直没(不会)写二进制优化初中就写 ...

  2. [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)

    [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...

  3. bzoj4182 Shopping 点分治+单调队列优化多重背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...

  4. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  5. Luogu 3423 [POI 2005]BAN-银行票据 (多重背包单调队列优化 + 方案打印)

    题意: 给出 n 种纸币的面值以及数量,求最少使用多少张纸币能凑成 M 的面额. 细节: 好像是要输出方案,看来很是头疼啊. 分析: 多重背包,裸体??? 咳咳,好吧需要低调,状态就出来了: dp [ ...

  6. [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)

    4182: Shopping Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 374  Solved: 130[Submit][Status][Disc ...

  7. POJ 1742 (单调队列优化多重背包+混合背包)

    (点击此处查看原题) 题意分析 给你n种不同价值的硬币,价值为val[1],val[2]...val[n],每种价值的硬币有num[1],num[2]...num[n]个,问使用这n种硬币可以凑齐[1 ...

  8. bzoj1531[POI2005]Bank notes 单调队列优化dp

    1531: [POI2005]Bank notes Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 559  Solved: 310[Submit][Sta ...

  9. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

随机推荐

  1. Microsoft office word关闭英文输入首字母大写设置

    1.概述: 在使用office word的时,经常出现输入一段不需首字母大写的英文时,通常敲击完回车时word会自动将首字母大写,需要重新将首字母修改成小写,这样操作很不方便.于是需要对这个功能进行一 ...

  2. 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, ...

  3. [每日一题] 11gOCP 1z0-052 :2013-09-1 RMAN-- repair failure........................................A20

    转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/10859315 正确答案:D 一.模拟上题的错误: 1.删除4号文件 [oracle@myd ...

  4. PHP手机获取6为不反复验证码

    //存数字数组 $code = array(); while(count($code) < 6){ //产生随机数1-9 $code[] = rand(1,9); //去除数组中的反复元素   ...

  5. 一个备份MySQL数据库的简单Shell脚本(转)

    Shell脚本是我们写不同类型命令的一种脚本,这些命令在这一个文件中就可以执行.我们也可以逐一敲入命令手动执行.如果我们要使用shell脚本就必须在一开始把这些命令写到一个文本文件中,以后就可以随意反 ...

  6. BZOJ 2525 Poi2011 Dynamite 二分答案+树形贪心

    题目大意:给定一棵树,有一些点是关键点,要求选择不超过mm个点.使得全部关键点到近期的选择的点距离最大值最小 二分答案,问题转化为: 给定一棵树,有一些点是关键点,要求选择最少的点使得每一个关键点到选 ...

  7. IOS-UIProgressView的简单介绍

    IOS-UIProgressView的简单介绍 转载:http://blog.sina.com.cn/s/blog_9c2363ad0101e1jy.html // UIProgressView的使用 ...

  8. IOS-tableViewCell重用机制

    IOS-tableViewCell重用机制 首先介绍tableViewCell原生cell的使用和重用机制 使用dequeueReusableCellWithIdentifier方法,这个方法会从缓存 ...

  9. myeclipse配置svn亲测

    1.安装目录更改为myeclipse install 目录:E:\MyEclipse85\MyEclipse 8.5common 目录:           E:\MyEclipse85\Common ...

  10. Java基础知识强化之集合框架笔记30:集合之泛型的引入

    1. 泛型的引入: (1)首先我们看看下面这一段代码,如下: package cn.itcast_01; import java.util.ArrayList; import java.util.It ...