1、B站:E13 背包DP 多重背包 单调队列优化_哔哩哔哩_bilibili
题目链接:宝物筛选 - 洛谷
#include <bits/stdc++.h>
using namespace std;
const int N=4000005;
int n,m,w,v,s;
int f[N],g[N],q[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
memcpy(g,f,sizeof(f));
cin>>v>>w>>s;
for(int j=0;j<v;j++){
int h=1,t=0;
for(int k=j;k<=m;k+=v){
while(h<=t&&g[k]>=g[q[t]]+(k-q[t])/v*w)t--;//当前元素更优,队尾出队
q[++t]=k;//队尾入队(下标)
if(q[h]<k-s*v)h++;//队头出队
if(h<=t)f[k]=max(g[k],(g[q[h]])+(k-q[h])/v*w);//输出最大值
}
}
}
cout<<f[m];
return 0;
}
题目链接:宝物筛选 - 洛谷
#include <bits/stdc++.h>
using namespace std;
const int N=40005;
int n,W,w,v,m;
int f[N],g[N];
int q[N];
int main(){
scanf("%d%d",&n,&W);//宝物总数与最大载重
for(int i=1;i<=n;i++){//枚举宝物
memcpy(g,f,sizeof(f));//f备份到g
scanf("%d%d%d",&v,&w,&m);
for(int j=0;j<w;j++){//分成w个类
int h=1,t=0;
for(int k=j;k<=W;k+=w){
while(h<=t&&g[k]>=g[q[t]]+(k-q[t])/w*v)t--;
q[++t]=k;
if(q[h]<k-m*w)h++;
if(h<=t)f[k]=max(g[k],g[q[h]]+(k-q[h])/w*v);
}
}
}
printf("%d\n",f[W]);
return 0;
}