平分娃娃(多重背包+二进制枚举)
蒜头君酷爱收集萌萌的娃娃。蒜头君收集了 6 种不同的娃娃,第 i 种娃娃的萌值为 i(1≤i≤6)。
现在已知每种娃娃的数量 mi ,蒜头君想知道,能不能把娃娃分成两组,使得每组的娃娃萌值之和相同。
输入格式
输入一行,输入6个整数,代表每种娃娃的数量mi(0≤mi≤20000)。
输出格式
输出一行。如果能把所有娃娃分成萌值之和相同的两组,请输出Can be divided.,否则输出Can't be divided.。
样例输入1
2 0 1 1 2 1
样例输出1
Can't be divided.
样例输入2
2 2 2 2 2 2
样例输出2
Can be divided.
本题为裸的多重背包。
计算dp[sum/2]的背包是否可以放满。
但是由于mi太大,会超时,所以我们做了一个处理。使用二进制思想,枚举出所有的个数。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 #include <ctime> 14 const int INF=0x3f3f3f3f; 15 typedef long long LL; 16 const int mod=1e9+7; 17 const LL MOD=1e9+7; 18 const double PI = acos(-1); 19 const double eps =1e-8; 20 #define Bug cout<<"---------------------"<<endl 21 const int maxn=1e5+10; 22 using namespace std; 23 24 int a[10]; 25 int dp[300010]; 26 27 int main() 28 { 29 #ifdef DEBUG 30 freopen("sample.txt","r",stdin); 31 #endif 32 // ios_base::sync_with_stdio(false); 33 // cin.tie(NULL); 34 35 int sum=0; 36 for(int i=1;i<=6;i++) 37 { 38 scanf("%d",&a[i]); 39 sum+=i*a[i]; 40 } 41 int flag=0; 42 if((sum&1)==0) 43 { 44 sum/=2; 45 for(int i=1;i<=6;i++) 46 { 47 int k; 48 for(k=1;k*2<1+a[i];k<<=1) //二进制枚举 49 { 50 for(int j=sum;j>=i*k;j--) 51 { 52 dp[j]=max(dp[j],dp[j-i*k]+i*k); 53 } 54 } 55 k=a[i]-k+1; //把剩下的几个补上 56 for(int j=sum;j>=i*k;j--) 57 { 58 dp[j]=max(dp[j],dp[j-i*k]+i*k); 59 } 60 } 61 if(sum==dp[sum]) flag=1; 62 } 63 if(flag==0) printf("Can't be divided.\n"); 64 else printf("Can be divided.\n"); 65 66 return 0; 67 }
-