标签:
1到6的卡分别各有有限制的张数,问能不能恰好分,总张数不能超过20000.
很明显是多重背包问题,上去果写了个三重循环,然后就T了,重新打开背包九讲,找到了多重背包的二进制拆分优化,把其中一维n的复杂度简化为logn的复杂度。
二进制拆分优化:就是1,2,4,2^k(满足和小于分解数最大的k),二进制优化可行的原因,因为可以用二进制数表示任意不同小于等于k的数。
注意:数组不要开小,RE了
#include<cstdio> #include<algorithm> #include<cmath> #include<map> #include<iostream> #include<vector> #include<cstring> #include<queue> #include<string> using namespace std; int a[7]; int dp[60005]; int sum=0; int num[60006]; int kk; void bin(int n,int k) //多重背包的二进制拆分 { int i,x; for(i=0; ; i++) { x = 1<<i; if(k<x) break; k-=x; num[kk++] = x*n; } if( k != 0 ) num[kk++] = n*k; } int main() { // freopen("input.txt","r",stdin); int cas=1; while(1) { memset(num,0,sizeof(num)); memset(dp,0,sizeof(dp)); kk=0; sum=0; for(int i=1;i<7;i++) { scanf("%d",&a[i]); sum+=a[i]*i; bin(i,a[i]); } if(!sum) break; printf("Collection #%d:\n",cas++); if(sum%2==1) { printf("Can‘t be divided.\n\n"); continue; } sum/=2; // printf("%d\n",kk); for(int i=0;i<kk;i++)//01 for(int k=sum;k>=num[i];k--) { dp[k]=max(dp[k],dp[k-num[i]]+num[i]); } if(dp[sum]==sum) { printf("Can be divided.\n\n"); } else { printf("Can‘t be divided.\n\n"); } } }
标签:
原文地址:http://www.cnblogs.com/acliang/p/4928058.html