JZOJ 4224. 食物
题目
分析
-
首先,很显然是两个多重背包
- 但是我们发现如果裸着跑的话一定会TLE
- 所以我们要尝试优化背包
- 我们这里采用二进制优化
- 首先我们能知道
- 二进制能组成任何一个数
- 如果我们将背包的个数k拆解出来就好了
- 拆成 1,2,4,8,16……
- 剩下的就再DP一次就好了
- 简单讲就是就是拆成二进制
- 比如说数量为3 不就是1+2吗
- 所以我们只需要DP一下1,2就能得到答案了
- 时间复杂度大大减少
代码
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 int f[50010],g[50010]; 6 void dp(int x,int y) 7 { 8 for (int i=20000;i>=x;i--) 9 f[i]=max(f[i],f[i-x]+y); 10 } 11 void dp1(int x,int y) 12 { 13 for (int i=50000;i>=x;i--) 14 g[i]=max(g[i],g[i-x]+y); 15 } 16 int main () 17 { 18 ios::sync_with_stdio(false); 19 int T; 20 cin>>T; 21 for (int i=1;i<=T;i++) 22 { 23 int n,m,p; 24 cin>>n>>m>>p; 25 memset(f,0,sizeof(f)); 26 memset(g,0,sizeof(g)); 27 for (int i=1,t,u,v;i<=n;i++) 28 { 29 cin>>t>>u>>v; 30 for (int j=1;j<=v;v-=j,j*=2) 31 dp(u*j,t*j); 32 if (v) dp(u*v,t*v); 33 } 34 for (int i=1,x,y,z;i<=m;i++) 35 { 36 cin>>x>>y>>z; 37 for (int j=1;j<=z;z-=j,j*=2) 38 dp1(y*j,x*j); 39 if (z) dp1(y*z,x*z); 40 } 41 int ans=0; 42 for (int i=1;i<=50000;i++) 43 if (f[g[i]]>=p) { 44 ans=i; 45 break; 46 } 47 if (ans) cout<<ans<<endl; 48 else 49 cout<<"TAT"<<endl; 50 } 51 }
为何要逼自己长大,去闯不该闯的荒唐