平分娃娃(多重背包+二进制枚举)

蒜头君酷爱收集萌萌的娃娃。蒜头君收集了 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 }

-

猜你喜欢

转载自www.cnblogs.com/jiamian/p/12216396.html