当前位置: 首页 > web >正文

【题解】洛谷P1776 宝物筛选 [单调队列优化多重背包]

 二进制优化还是不够快,如果我们想时间复杂度为 O(NW) ,还得找新的方法。

(W 为背包最大可承载量,N 为物品种类数)

例题:P1776 宝物筛选 - 洛谷

原来的转移式很普通:

f[i][j]=max(f[i-1][j-k*w]+k*v)\ (k<=m)

注意到对于每个 f[i][j],有一个特定的取值范围

而且答案是取该范围内的极值(最大或最小)

最重要的,对于每个最优决策点 j - k * w,具有单调性,随着 i 的增长是单调递增的。

这种情况下可以用单调队列优化

队首保存最优决策点,每次将不符合条件(超出范围)的队首弹出。

上面那个式子,可以化为:

整体:

f[i]=f[i-1]

而对于单种物体

f[i][j+k*w]=max(f[i][j+k'*w]-k'*v)+k*v

取值范围:\ (k-k'\leq m\ and\ k\leq \left \lfloor \frac{W-j}{m} \right \rfloor)

其实就是把原来式子里的 k 换成了 k-k'

之所以要写成这一坨,

是要让 f[i][j+k*w] 和 f[i][j+k'*w] 的格式一样,方便单调队列

但是注意到 k\leq \left \lfloor \frac{W-j}{m} \right \rfloor,而不是 k\leq m

这是为什么呢?不会越界吗?

这是因为背包有个特点,f[i][j] 占背包的空间不一定就是 j,但一定比 j 小

所以 f[i][j+k'*w] 也不一定就真的放了 k' 个当前物品,只是长这个样子。

f[i][j+k*w]=max(f[i][j+k'*w]-k'*v)+k*v

所以上面这整个式子,真正当前物品被放进去的个数是 k-k'

把转移式化成这样,其实已经很快了。

但还能更快,我们知道  f[i][j+k*w] 只跟 f[i][j+k'*w] 有关系。

也就是我们枚举 j,而 j 是 W\ mod\ w 的余数

讲了这么多,看看代码吧:

#include<bits/stdc++.h>
using namespace std;typedef long long LL;
const int N = 4e4 + 10;struct node {LL x;   //f[j + k * w] - k * vint k;   // k值
} q[N];LL f[N];int main() {ios::sync_with_stdio(false);cin.tie(0);int n; LL W;cin >> n >> W;LL sum = 0, ans = 0;for (int i = 1; i <= n; i++) {LL v, w; int m;cin >> v >> w >> m;if (w == 0) {      //如果这个宝物重量为 0,那就直接加上sum += v;continue;}int K = W / w;   //最大可选数量m = min(m, K);for (int j = 0; j < w; j++) {    //枚举余数 jint head, tail;    head = 1; tail = 0;    //队头队尾初始化LL r = (W - j) / w;    // k 的上限for (int k = 0; k <= r; k++) {while(head <= tail && f[j + k * w] - k * v >= q[tail].x) {tail--;     //当前 k 比队尾优而且比队尾后,踢队尾}tail ++;q[tail].k = k;                    // 记录物品数量q[tail].x = f[j + k * w] - k * v;    // 记录对应的 f 值while(head <= tail && k - q[head].k > m) {     //队头在不在可选域head++;}if (head <= tail) {f[j + k * w] = max(f[j + k * w], q[head].x + k * v);    //更新 fans = max(ans, f[j + k * w]);   //找最大的 f}}}}// f[W] + sum 也一样cout << sum + ans << "\n";return 0;
}

http://www.xdnf.cn/news/20001.html

相关文章:

  • C++----模板特化以及模板声明与定义分离问题
  • AT32网线拔插下,modbus tcp断线重连
  • Linux awk命令完全指南:从原理到实战,搞定文本处理难题
  • 【AI】人工智能 传统和现代 架构和算法的演变历史
  • windows安装谷歌浏览器地址
  • TypeScript `infer` 关键字详解(从概念到实战)
  • AGV 搬运小车路径规划:从地图构建到路径决策的技术全解析
  • 打通 Flutter 与原生状态管理:Android ViewModel 的运用
  • SpringBoot+PDF.js实现按需分片加载(包含可运行样例源码)
  • C++小游戏
  • 腾讯开源HunyuanWorld-Voyager突破性原生3D重建与视频扩散框架
  • 计算机大数据毕业设计选题:基于Spark+hadoop的全球香水市场趋势分析系统
  • 优思学院|5个为什么(5 Whys)分析法一文讲清楚
  • AI编写自动点击器 - 毫秒级精准鼠标连点器
  • kafka:【1】概念关系梳理
  • kvm 虚拟机如何安装 qemu-guest-agent
  • kali_linux
  • 【Linux】线程封装
  • 【FastDDS】Layer DDS之Domain ( 04-DomainParticipantFactory)
  • 采用基于模型的方法实现车辆SOA威胁分析自动化
  • wpf 自定义密码文本框,并且可以双向绑定
  • 吱吱企业通讯软件以安全为核心,构建高效沟通与协作一体化平台
  • 什么是Agent?小白如何学习使用Agent?一篇文档带你详细了解神秘的Agent
  • 容器tomcat镜像制作
  • 算法题2:动态规划
  • Python委托迭代完全指南:从基础到高级设计模式实践
  • Vision Pro图像处理工具全解析
  • Hadoop HDFS-SecondaryNameNode(2nn)详细介绍
  • PPI网络与TF-miRNA调控网络的实现方法(基于《列腺癌研究.pdf》)
  • 跟做springboot尚品甄选项目