版权声明:原创博客 喜欢拿走 https://blog.csdn.net/qq_43004519/article/details/84584892
题目
蒜头君酷爱收集萌萌的娃娃。蒜头君收集了 6种不同的娃娃,第 i 种娃娃的萌值为 i(1≤i≤6)。现在已知每种娃娃的数量 mi,蒜头君想知道,能不能把娃娃分成两组,使得每组的娃娃萌值之和相同。
输入格式
输入一行,输入 6 个整数,代表每种娃娃的数量 mi(0≤mi≤20,000)。
输出格式
输出一行。如果能把所有娃娃分成萌值之和相同的两组,请输出Can be divided.,否则输出Can’t be divided.。
分析
核心思想:01背包+二进制思想
其实不难,我们只要求出萌值的一半,假设第一个娃娃有n个,那我们就可以划分成1,2,4,8…2的k次方,n-(1+2+…2的k次方)个娃娃,这样就可以表示1…n的每一个数量。然后01背包判断dp[sum/2]==sum/2就可以了出结果了。
AC代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dp[1000000];
int m[7];
int val[200];
int main()
{
int sum=0,flag=1;
memset(dp,0,sizeof(dp));
//依据二进制思想,对m[i]个物品进行划分1,2,4,8....2的k次方,n-(1+2+..2的k次方)
for(int i=1;i<=6;i++){
cin>>m[i];
sum+=i*m[i];
for(int k=1;k<=m[i];k*=2){
val[flag++]=k*i;
m[i]-=k;
}
if(m[i]>0){
val[flag++]=m[i]*i;
}
}
if(sum%2==0){//01背包问题
sum/=2;
for(int i=1;i<flag;i++){//外层是物品的依次递增
for(int j=sum;j>=val[i];j--){//限制条件是萌值不超过总和的一半,
dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
}
}
if(dp[sum]==sum)
cout<<"Can be divided."<<endl;
else
cout<<"Can't be divided."<<endl;
}
else
cout<<"Can't be divided."<<endl;
return 0;//give me five
}