[CodeVS 3269]混合背包
哎……现在才敢说真正会背包DP……
这个题可以分成三类问题分别处理,然后用一个一维数组一起递推。
0-1背包和完全背包都很简单。多重背包直接递推的话复杂度很高,可以考虑单调队列优化……然而窝太弱……不过还是用了
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #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; } |