题目链接:

6. 多重背包问题 III - AcWing题库​www.acwing.com背包九讲bilibili​www.bilibili.com

闫学灿大神的背包九讲到两种完全背包问题的优化算法,第一种是通过二进制拆包将时间复杂度从N*S*M降低到N*logS*M。第二种是通过单调队列将算法的时间复杂度进一步降到N*M。不过视频讲解太快,思路没跟上来。核心代码就四五行,但是没有理解思路的话是很难看懂的,我花了一天时间才算看明白。网络上找到的资料要么排版太差,要么就是符号不一致,看起来很费力,所以干脆自己整理一份资料。

设N表示有多少种物品,C[i]记录每种物品的容量,W[i]记录每种物品的价值,S[i]记录每种最多能放多少个,M表示背包的容量。如果是一路看大雪菜视频过来的话,很容易得到状态转移方程:

从公式中可以看出f[j]和f[j+c]都是从s+1个数里面取最大值,计算f[j+c]时只是将滑动窗口右移了一步,类似下图的效果:

只不过移动的时候,前面的s个元素都增加了w,每个元素加上相同的数不影响计算最大值。使用单调队列可以在O(N)时间复杂度下找到所有滑动窗口的最大值,关于单调队列处理滑动窗口的问题可以看看这篇文章:

labuladong:特殊数据结构:单调队列​zhuanlan.zhihu.com

容易知道f[j]的计算只依赖于g[k],其中j%c = k%c。因此可以将g[0~m]按%c的余数进行分类:

g[0],g[c],g[2c],g[3c],...

g[1],g[1+c],g[1+2c],g[1+3c],...

...

g[c-1],g[2c-1],g[3c-1],g[4c-1]...

每个分类可以计算出:

f[0],f[c],f[2c],f[3c],...

f[1],f[1+c],f[1+2c],f[1+3c],...

...

f[c-1],f[2c-1],f[3c-1],f[4c-1]...

从而整个f[0~m]都能计算出来。

上面的讲解可能有点啰嗦,归纳起来就两点:

  1. 需要将所有状态按照%c的余数进行分类,每个分类可以计算出下一层对应的分类
  2. 计算下一层对应分类的过程类似于滑动窗口取最大值,利用单调队列可以实现O(N)的时间复杂度

综上所述,C++代码如下:

#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>using namespace std;int main() {int n, m;cin >> n >> m;deque<int> q;vector<int> f(m + 1), g(m + 1);for (int i = 0; i < n; ++i) {int c, w, s;cin >> c >> w >> s;swap(f, g);for (int j = 0; j < c; ++j) {q.clear();for (int k = j; k <= m; k += c) {f[k] = g[k];if (!q.empty() && k - s * c > q.front()) q.pop_front(); // 最多s+1个元素,超出个数限制则移除队首元素if (!q.empty()) f[k] = max(f[k], g[q.front()] + (k - q.front()) / c * w); // 队首肯定是最大的while (!q.empty() && g[q.back()] + (k - q.back()) / c * w <= g[k]) q.pop_back(); //将k压入队列前,先把所有比它小的出队q.push_back(k);}}}cout << f[m] << endl;return 0;
}

遗憾的是居然超时了。。。。。主要是因为deque.clear()太频繁了,每次clear都会清空内存,也不存在lazy clear的API。没办法只能用数组模拟队列了。最终提交通过的代码如下:

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int main() {int n, m;cin >> n >> m;int q[20010];vector<int> f(m + 1), g(m + 1);for (int i = 0; i < n; ++i) {int c, w, s;cin >> c >> w >> s;swap(f, g);for (int j = 0; j < c; ++j) {int hh = 0, tt = -1;for (int k = j; k <= m; k += c) {f[k] = g[k];if (hh <= tt && k - s * c > q[hh]) ++hh; // 最多s+1个元素,超出个数限制则移除队首元素if (hh <= tt) f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / c * w); // 队首肯定是最大的while (hh <= tt && g[q[tt]] + (k - q[tt]) / c * w <= g[k]) --tt; //将k压入队列前,先把所有比它小的出队q[++tt] = k;}}}cout << f[m] << endl;return 0;
}

说实话,这种第一次不照着答案敲是很难写对的,不过思路明白了下次写就容易很多了。

多重背包单调队列优化思路_单调队列优化多重背包问题相关推荐

  1. 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...

  2. 多重背包单调队列优化思路_多重背包之单调队列优化理论性总结

    多重背包之单调队列优化: 若用F[j]表示对容量为j的背包,处理完前i种物品后,背包内物品可达到的最大总价值,并记m = min(n, j / v).放入背包的第i种物品的数目可以是:0.1.2--, ...

  3. 多重背包单调队列优化思路_多重背包问题

    题目描述: 无优化版本: int main(){int m, n;cin >> n >> m;for(int i = 1; i <= n; ++i){int v , w, ...

  4. sql并发 锁 优化思路_并发优化–减少锁粒度

    sql并发 锁 优化思路 在高负载多线程应用程序中,性能非常重要. 开发人员必须意识到并发问题才能获得更好的性能. 当我们需要并发时,我们通常拥有必须由两个或更多线程共享的资源. 在这种情况下,我们处 ...

  5. oracle 10g 速度慢,让Oracle跑得更快—Oracle 10g性能分析与优化思路_数据库教程

    资源名称:让Oracle跑得更快-Oracle 10g性能分析与优化思路 内容简介: 在这本书里读者将会学到作者在性能优化方面的一些思路和思考,一些故障处理的方法和原则,这些东西是作者在实践中长期积累 ...

  6. sql优化的方法及思路_微生物发酵 技术优化思路 与方法

    发酵是细胞大规模培养技术中最早被人们认识和利用的.发酵技术在医药.轻工.食品.农业.环保等领域的广泛应用,使这一技术在国民经济发展中发挥着越来越重要的作用. 为了提高发酵生产水平,人们首先考虑的是菌种 ...

  7. 飞浆AI studio人工智能课程学习(2)-Prompt优化思路|十个技巧高效优化Prompt|迭代法|Trick法|通用法|工具辅助

    文章目录 优化思路 上节课的例子 问题分析 思路解析 Prompt优化技巧 Prompt优化原理 十个技巧高效优化Prompt 迭代法 Trick法 工具法 通用技巧│定基础 通用技巧│做强调 需求强 ...

  8. 优化 回归_使用回归优化产品价格

    优化 回归 应用数据科学 (Applied data science) Price and quantity are two fundamental measures that determine t ...

  9. python网页优化公司_使用python优化scipy.optimize.minimize公司

    我将逐行检查您的代码,并强调一些问题:from scipy.optimize import minimize import numpy as np prices=np.array([[1.5,50,3 ...

  10. 奇奇seo优化软件_信阳seo优化排名软件

    信阳seope4c65优化排名软件,5g时代的到来,使得很多企业对移动互联网的推广预算再次增加.究其原因,是移动互联网用户数量的增加,使得行业竞争对手增多,网络推广成本提高.如果预算不增加,企业网站的 ...

最新文章

  1. 在数组中查找一个数并输出所处位置
  2. Latex合并及插入图片相关问题
  3. 用私有构造器或者枚举类型强化Singleton 属性
  4. SSY and JLBD
  5. PHP 获取JSON json_decode返回NULL解决办法
  6. python图片保存重命名_Python实现重命名一个文件夹下的图片
  7. JeecgBoot 单表数据导出多sheet实例
  8. PTA-6-1 数组循环右移 (20分)(C语言)
  9. Sysbench压测
  10. Bezier(贝塞尔)曲线(五阶)的轨迹规划在自动驾驶中的应用(五)
  11. vue-cli 中stylus写样式莫名报错?
  12. 中文文本纠错算法实现
  13. 硕士转行学python_0基础转行编程学习Python是最快的途径吗?
  14. Linux与网络服务(零)从零开始聊聊Linux相关概念(科普向)
  15. 高斯函数及高斯滤波器
  16. iwconfig使用
  17. python爬取搜狗微信的推文
  18. DAPP 开发直通车-如何基于NEL 轻钱包来开发DAPP
  19. RabbitMQ3.10.7高级特性
  20. python读取中文txt乱码问题

热门文章

  1. pcl学习之kd-tree
  2. Focal Loss for Dense Object Detection解读
  3. layui,返回的数据不符合规范,正确的成功状态码 (code) 应为:0
  4. Vue生命周期-手动挂载理解
  5. 为什么RegisterClientScriptResource方法在自定义控件中的RenderContents期间不起作用?...
  6. 【OpenCV学习笔记】【编程实例】三(将一个图像中的指定区域拷贝到另一个图像的指定区域
  7. 【pytorch】(断点)继续上次训练
  8. 设置MySQL最大连接数
  9. android实现Materia Design风格APP(三):部分Materia Design风格的控件介绍二
  10. 四阶龙格库塔法的基本思想_“李军班长工作法”为“卓越班组”建设注入新动力...