多重背包的二进制优化
题目要求是把所有的物品分成两部分,使得两部分价值之和相等
可以先把总的价值之和m求出然后除2,(如果m是奇数,可以直接Can‘t)然后把第i种大理石分成a[i]个独立的物品,价值和费用都为i,然后把这些物品放入容量为m的背包,如果能恰好放满,则说明可以划分。
时间复杂度O(m*n)m最大为60000 n最大为20000,相乘得1.2*e9
显然会超时,需要优化。多重背包一般都需要二进制优化,这东西不想多说了,背包九讲上很详细(背包九讲真的很强大,你值得拥有!~) 完事,再用恰好装满的01背包算一下,如果dp[m]==m就can否则can‘t
背包九讲全部理解了,背包问题以后应该就不会出问题,所以继续吧。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define INF 11111111 6 using namespace std; 7 8 const int maxv = 60005; 9 const int maxn = 200; 10 int a[7],s[maxn],dp[maxv]; 11 int main() 12 { 13 //freopen("in.txt","r",stdin); 14 int m,n; 15 while(1) 16 { 17 int m = 0,cnt = 1; 18 for(int i = 1;i<=6;++i) 19 { 20 cin>>a[i]; 21 m = m+a[i]*i; 22 23 int k = 1; 24 while(a[i]>=k) 25 { 26 s[cnt++] = k*i; 27 a[i]-=k; 28 k*=2; 29 } 30 if(a[i])s[cnt++] = a[i]*i; 31 32 } 33 dp[0] = 0; 34 if(!m)return 0; 35 if(m%2){printf("Can‘t\n");continue;} 36 m/=2; 37 for(int i = 1;i<cnt;++i) 38 { 39 dp[i] = -INF; 40 for(int j = m;j>=s[i];--j) 41 dp[j]=max(dp[j],dp[j-s[i]]+s[i]); 42 } 43 if(dp[m]==m)printf("Can\n"); 44 else printf("Can‘t\n"); 45 } 46 return 0; 47 }
时间: 2024-10-07 09:34:08