P1776 宝物筛选_NOI导刊2010提高(02)

https://www.luogu.org/problemnew/show/P1776

模版的多重背包,但朴素肯定不行,这里采用单调队列优化

朴素方程式

 变形

(第一维压掉)

 如此,便可以用分mod用单调队列优化啦,代码如下

 

 

 1 #include <bits/stdc++.h>
 2 #define up(i,l,r) for(register int i = (l); i <= (r); ++i)
 3 #define dn(i,l,r) for(register int i = (l); i >= (r); --i)
 4 #define ll long long
 5 #define re register
 6 #define _N putchar('\n')
 7 using namespace std;
 8 
 9 template <typename T> void in(T &x) {
10     x = 0; T f = 1; char ch = getchar();
11     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
12     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
13     x *= f;
14 }
15 
16 template <typename T> void out(T x) {
17     if(x < 0) x = -x , putchar('-');
18     if(x > 9) out(x/10);
19     putchar(x%10 + 48);
20 }
21 //---------------------------------------------------------------
22 
23 const int N = 40007;
24 
25 int n,max_w,tmp,ans,f[N],num[N];
26 
27 struct {
28     int pos,v;
29 }que[N];
30 
31 int main() {
32     freopen("0.in","r",stdin);
33     in(n); in(max_w);int v,w,cnt;
34     for(int i = 1; i <= n; ++i) {
35         in(v); in(w); in(cnt);
36         if(!w) {
37             tmp += cnt * v; continue;
38         }
39         int a = min(cnt,max_w/w);
40         for(int mod  = 0; mod < w; ++mod) {
41             int head = 0,tail = 0,c = (max_w-mod)/w;
42             for(int k = 0; k <= c; ++k) {
43                 int add = f[k*w+mod] - k*v;
44                 while(head < tail && add >= que[tail-1].v) --tail;
45                 ++tail; que[tail-1].v = add,que[tail-1].pos = k;
46                 
47                 while(head < tail && que[head].pos + a < k) ++head;
48                 
49                 f[k*w+mod] = max(f[k*w+mod],que[head].v + k*v);//
50                 ans = max(ans,f[k*w+mod]);
51             }
52         }
53     }
54     out(ans+tmp);
55     return 0;
56 }

 

 

 

posted @ 2019-07-12 17:12  陈星卿  阅读(155)  评论(0编辑  收藏  举报