传送门:https://www.luogu.org/problem/P1776

很久就想用二进制拆分做一下了,这道题本来是用单调队列优化可惜蒟蒻我不会。

于是我就用二进制拆分牺牲空间复杂度换来了时间复杂度。

任何一个数都可以拆成二进制(其实不鬼畜)

e.g. 15=1+2+4+8    7=1+2+4 而拆出的这些数可以组成比这个数小的任意值。

所以代码如下

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<stack>
 5 #include<cstring>
 6 #include<cmath>
 7 using namespace std;
 8 int n,w;
 9 struct thing{
10     int v,w;
11 }lis[1000005];
12 int tot;
13 int f[1000005];
14 inline int kd()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
18     while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
19     return x*f;
20 }
21 int main()
22 {
23     n=kd(),w=kd();
24     for(register int i=1;i<=n;i++)
25     {
26         int x=1;
27         int a=kd(),b=kd(),c=kd();
28         while(c-x>=0)//二进制拆分本尊 
29         {
30             c-=x;
31             lis[++tot].w=x*a;
32             lis[tot].v=x*b;
33             x<<=1;
34         }
35         if(c!=0)//判断是否还有剩下的 
36         {
37             lis[++tot].w=c*a;
38             lis[tot].v=c*b;
39         }
40     }
41     for(register int i=1;i<=tot;i++)//普通的01背包乖乖 
42     {
43         for(register int j=w;j>=lis[i].v;j--)
44         {
45             f[j]=max(f[j],f[j-lis[i].v]+lis[i].w);
46         }
47     }
48     cout<<f[w];
49 }

  

01-02 00:47