hdu-1059(多重背包+二进制优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1059

题意:输入6个数,每个数ni代表价值为i的物品有ni个。求如果这些物品能均分给两个人,每个人获得的物品的总价值

相同,就输出“Can be divided.”,否则输出“Can't be divided.”;具体格式见输出格式。

思路:本来想用dfs做的,后来发现时间超限了,其实可以用多重背包来做,

每个物品的数量有限,找出是否存在几个物品的价值与物品总价值的一半相同。

参考文章:https://blog.csdn.net/aaaaacmer/article/details/48543575

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100100],a[20],sum;
void f(int cost,int num)
{
    int i;
    if(cost*num>=sum)
    {
        for(i=cost;i<=sum;i++)
        dp[i]=max(dp[i],dp[i-cost]+cost);
        return ;
    }
    int k=1;
    while(k<num)
    {
        for(i=sum;i>=k*cost;i--)
        dp[i]=max(dp[i],dp[i-cost*k]+cost*k);
        num-=k;
        k*=2;
    }
    for(i=sum;i>=num*cost;i--)
    dp[i]=max(dp[i],dp[i-cost*num]+cost*num);
}
int main(void)
{
    int pt=1,i,j;
    while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6])
    {
        if(!a[1]&&!a[2]&&!a[3]&&!a[4]&&!a[5]&&!a[6]) break;
        sum=0;
        for(i=1;i<=6;i++) sum+=a[i]*i;
        printf("Collection #%d:
",pt++);
        if(sum%2)
        {
            printf("Can't be divided.

");
            continue;
        }
        sum/=2;
        memset(dp,0,sizeof(dp));
        for(i=1;i<=6;i++) f(i,a[i]);
        if(dp[sum]==sum) printf("Can be divided.

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

");
    }
    return 0; 
}
原文地址:https://www.cnblogs.com/2018zxy/p/9747969.html