博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[总结] 单调队列优化多重背包学习笔记
阅读量:5154 次
发布时间:2019-06-13

本文共 1083 字,大约阅读时间需要 3 分钟。

使用单调队列,可以把求解多重背包问题的复杂度进一步优化到 $O(NM)$

把状态 j 按照除以 $V_i$ 的余数分组,对每一组分别进行计算,不同组之间的状态在阶段 i 不会互相转移。

上代码

for(int i=1;i<=n;i++){
    scanf("%d%d%d",&v[i],&w[i],&c[i]);     for(int u=0;u
=std::max(maxp-c[i],0);j--){             while(l<=r&&calc(q[r],u,i)<=calc(j,u,i)) r--;             q[++r]=j;         }         for(int j=maxp;~j;j--){
            while(l<=r&&q[l]>j-1) l++;             if(l<=r)   //这句不能忘!!                f[u+j*v[i]]=std::max(f[u+j*v[i]],f[u+q[l]*v[i]]+(j-q[l])*w[i]);             if(j-c[i]-1>=0){
                while(l<=r&&calc(q[r],u,i)<=calc(j-c[i]-1,u,i)) r--;                 q[++r]=j-c[i]-1;             }         }     } }

代码中的几句话有必要解释一下

for(int j=maxp-1;j>=std::max(maxp-c[i],0);j--)
 
这里是预处理,为了让状态能够转移到 maxp,此后队头保存的一直是 j-1 ~ j-c[i] 的最大值
while(l<=r&&q[l]>j-1) l++;
 
q[l]>j-1 的意义是不让 q[j] 转移到 q[j]
if(j-c[i]-1>=0){
    while(l<=r&&calc(q[r],u,i)<=calc(j-c[i]-1,u,i)) r--;         q[++r]=j-c[i]-1; }
 
这里的目的是更新队尾,也就是随着 j 的减小,可以从更靠前的状态转移来,但是从 j-1 ~ j-c[i] 都已经在之前更新过队尾了,所以这里更新 j-c[i]-1

转载于:https://www.cnblogs.com/YoungNeal/p/8798925.html

你可能感兴趣的文章
onlevelwasloaded的调用时机
查看>>
求出斐波那契数组
查看>>
Vue.js 基础学习之组件通信
查看>>
lr_start_transaction/lr_end_transaction事物组合
查看>>
每天一个Linux命令 - 【chkconfig】
查看>>
△UVA10106 - Product(大数乘法)
查看>>
golang (7) 文件操作
查看>>
关于 Object.defineProperty()
查看>>
免认证的ssh登录设置
查看>>
[转] Maven 从命令行获取项目的版本号
查看>>
CodeIgniter学习笔记(四)——CI超级对象中的load装载器
查看>>
.NET CLR基本术语
查看>>
Java Development Environment in Linux: Install and Configure Oracle
查看>>
Delphi XE2 update4 很快就要来了
查看>>
Mac 关机卡住
查看>>
ssm开发随笔
查看>>
fidder使用
查看>>
circos的ubuntu和mac安装
查看>>
C - Heavy Transportation
查看>>
ubuntu的home目录下,Desktop等目录消失不见
查看>>