HDU1059 【DP·二进制数优化】

题意:
有6种不同价值的物品,然后问你能不能分成两半使得两堆价值相等;
思路:
一共有20000*6=120000 多的价值,
总共背包有20000个,价值最大是120000,看看能不能DP到value/2就好了,所以DP数组可以开60000;
价值乘以背包数,复杂度好大?
我们知道一个数的组成可以搞成一个二进制,所以对于每个背包的数量,都可以搞成几个二进制数的背包数量

那么就是有那么多背包,简单DP一下就好了;

#include<bits/stdc++.h>
using namespace std;

const int N=6e4+10;
int num[7];
bool dp[N];

int main()
{
    int cas=1;
    while(1)
    {
        bool flag=false;
        int sum=0;
        for(int i=1;i<=6;i++)
        {
            scanf("%d",&num[i]);
            sum+=num[i]*i;
            if(num[i])
                flag=true;
        }
        if(!flag) break;
        printf("Collection #%d:
",cas++);
        if(sum%2)
        {
            printf("Can't be divided.

");
            continue;
        }
        memset(dp,0,sizeof(dp));
        sum/=2;
        int k,w;
        dp[0]=true;
        for(int i=1;i<=6;i++)
        {
            k=1;
            while(k<=num[i])
            {
                w=k*i;
                for(int j=sum;j>=w;j--)
                {
                    if(dp[j-w])
                        dp[j]=1;
                }
                num[i]-=k;
                k<<=1;
            }
            w=num[i]*i;
            for(int j=sum;j>=w;j--)
                if(dp[j-w])
                    dp[j]=1;
        }
        if(dp[sum])
            printf("Can be divided.

");
        else
            printf("Can't be divided.

");
    }
    return 0;
}





原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777476.html