1 条题解
-
0
自动搬运
来自洛谷,原作者为

ezoiHQM
**搬运于
2025-08-24 21:28:58,当前版本为作者最后更新于2018-05-26 07:41:30,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
为什么都没有人用单调队列? 那就补一发单调队列优化多重背包吧。 w表示物品重量,v表示价值,c表示数量,我们知道朴素状态转移方程:
f[i][j]=max(f[i−1][j−w∗k]+v∗k);(k<=c)现在我们要把这个方程变成一个单调队列可以优化的形式,于是我们假设:d=j mod w[i],s=⌊j/w[i]⌋
f[i][j]=max(f[i−1][d+w∗k]−v∗k)+v∗s(s-k<=c)之后我们枚举余数d,然后对于每个余数d都用单调队列优化即可。
#include<cstdio> #include<algorithm> using namespace std; int n,V,ans,head,tail,q[40010],q2[40010],dp[40010]; int main(){ scanf("%d%d",&n,&V); for(int i=1;i<=n;i++){ int v,w,c; scanf("%d%d%d",&w,&v,&c); if(v==0){ ans+=w*c; continue; } int k=V/v; c=min(c,k); for(int d=0;d<v;d++){ head=tail=0; k=(V-d)/v; for(int j=0;j<=k;j++){ while(head<tail&&dp[d+j*v]-j*w>=q2[tail-1]) tail--; q[tail]=j; q2[tail++]=dp[d+j*v]-j*w; while(head<tail&&q[head]<j-c) ++head; dp[d+j*v]=max(dp[d+j*v],q2[head]+j*w); } } } printf("%d",ans+dp[V]); return 0; }
- 1
信息
- ID
- 749
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者