平分娃娃

版权声明:原创博客 喜欢拿走 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
}

猜你喜欢

转载自blog.csdn.net/qq_43004519/article/details/84584892