[CodeVS 3269]混合背包
哎……现在才敢说真正会背包DP……
这个题可以分成三类问题分别处理,然后用一个一维数组一起递推。
0-1背包和完全背包都很简单。多重背包直接递推的话复杂度很高,可以考虑单调队列优化……然而窝太弱……不过还是用了
代码:
#include <cstdio> #include <algorithm> #include <queue> #include <deque> using namespace std; const int maxn=201,maxv=200001; struct DQueue{ deque<int> D; queue<int> Q; void push(int x){ Q.push(x); while(!D.empty() && x>D.back()) D.pop_back(); D.push_back(x); } int top(){ return D.front(); } void pop(){ if(D.front()==Q.front()) D.pop_front(); Q.pop(); } int size(){ return Q.size(); } void clear(){ while(!Q.empty()) Q.pop(); D.clear(); } }; int d[maxv]; int v; void pack(int V,int W,int c){ register int i,j,m; if(c==1){ for(i=v;i>=V;i--) d[i]=max(d[i],d[i-V]+W); }else{ if(c==-1){ for(i=V;i<=v;i++) d[i]=max(d[i],d[i-V]+W); }else{ c=min(c,v/V); for(i=0;i<V;i++){ m=(v-i)/V; DQueue Q; for(j=0;j<=m;j++){ if(Q.size()==c+1) Q.pop(); Q.push(d[j*V+i]-j*W); d[j*V+i]=Q.top()+j*W; } } } } } int main(){ register int i; int n,x,y,z; scanf("%d%d",&n,&v); for(i=1;i<=n;i++){ scanf("%d%d%d",&x,&y,&z); pack(x,y,z); } printf("%d\n",d[v]); return 0; }