传送门: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 }