题目链接:https://www.luogu.org/problem/P1776
单调队列,就是在区间移动时动态维护区间的最值
看了蛮久还是蛮晕的,看不太明白,因为单调队列和多重背包都很不熟,不想继续在这个知识点上浪费时间了,就先记住模板吧,之后题做多了,写题时遇到了,多多温习。
看的几篇博客:https://blog.csdn.net/qq_40679299/article/details/81978770
https://www.cnblogs.com/-guz/p/9866118.html
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; const int inf=1<<30; const int maxn=4e4+7; int dp[maxn],q[maxn],p[maxn]; int main(){ int n,W;cin>>n>>W; int ans=0; for(int i=1;i<=n;i++){ int v,w,num;scanf("%d%d%d",&v,&w,&num); if(w==0)ans+=v*num; num=min(W/w,num);//最大能够承载的该物品的数量 for(int d=0;d<w;d++){//枚举重量的余数 int head=0,tail=0; int k=(W-d)/w;//我们转换后的表达式为dp[d+k*w]-k*v,所有我们要保证d+k*w<=W for(int j=0;j<=k;j++){ while(head<tail&&dp[d+j*w]-j*v>=q[tail-1])tail--; q[tail]=dp[d+j*w]-j*v;p[tail++]=j; while(head<tail&&p[head]<j-num)head++; dp[d+j*w]=max(dp[d+j*w],q[head]+j*v); } } } cout<<dp[W]+ans<<endl; return 0; }