题目链接:https://www.luogu.org/problem/P1833
题意:有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包),应该怎么求解。
分析:这个题其实一点都不难,之所以写题解是提醒自己记住这个写法,直接根据一个物品的数量判断是什么背包,然后直接写那个背包的写法即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; const int inf=1<<30; const int maxn=1e4+7; int dp[maxn],q[maxn],pa[maxn]; int main(){ int h1,h2,m1,m2,V; scanf("%d:%d",&h1,&m1);scanf("%d:%d",&h2,&m2); if(h1==h2) V=m2-m1; else V=(h2-h1-1)*60+m2+60-m1; int v,w,p; int n;scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d",&w,&v,&p); if(p==0){ for(int j=w;j<=V;j++){ dp[j]=max(dp[j],dp[j-w]+v); } } else if(p==1){ for(int j=V;j>=w;j--){ dp[j]=max(dp[j],dp[j-w]+v); } } else { p=min(p,V/w); for(int d=0;d<w;d++){ int tail=0,head=0; int k=(V-d)/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;pa[tail++]=j; while(head<tail&&pa[head]<j-p) head++; dp[d+j*w]=max(dp[d+j*w],q[head]+j*v); } } } } cout<<dp[V]<<endl; return 0; }