Dividing (多重背包 搜索)

/*
第一个多重背包题目 真的不理解二进制优化
*/http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?cid=10594&pid=1001&ojid

以下是用二进制优化的 不会超时

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[200000],a[7];
void zeroOne(int weiht,int value,int c)
{
    for(int j=c;j>=weiht;j--)
        dp[j]=max(dp[j],dp[j-weiht]+value);
}
void complelet(int weight,int value,int c)
{
    for(int j=weight;j<=c;j++)
        dp[j]=max(dp[j],dp[j-weight]+value);
}
void duoChong(int weight,int value,int count,int c)
{
    if(count*value>=c)complelet(weight ,value,c);
    else
        {
            int k=1;
            while(k<count)
            {
                zeroOne(k*weight,k*value,c);
                count-=k;
                k+=k;
            }
             zeroOne(count*weight,count*value,c);
        }
}
int main()
{
    int count=0;
    while(1)
    {
        int sum=0;
        for(int i=1; i<=6; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i]*i;

        }
        if(sum==0)break;
        printf("Collection #%d:\n",++count);
        if(sum%2==1)
        {
            printf("Can't be divided.\n\n");
            continue;
        }
        int c=sum/2;
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=6; i++)
             duoChong(i,i,a[i],c);
        if(dp[c]==sum/2)printf("Can be divided.\n\n");
        else printf("Can't be divided.\n\n");
    }
    return 0;
}

直接化为01背包计算 超时

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[200000],a[7],w[7];
int main()
{
    int count=0;
    while(1)
    {
        int sum=0;
        for(int i=1; i<=6; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i]*i;
            w[i]=i;
        }
        if(sum==0)break;
        printf("Collection #%d:\n",++count);
        if(sum%2==1)
        {
            printf("Can't be divided.\n\n");
            continue;
        }
        int c=sum/2;
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=6; i++)
            for(int k=1; k<=a[i]; k++)//有限个数量(超时)
                for(int j=c; j>=w[i]; j--)
                    dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
                    printf("sum/2=%d\n",dp[sum/2]);
        if(dp[c]==sum/2)printf("Can be divided.\n\n");
        else printf("Can't be divided.\n\n");
    }
    return 0;
}

下面是搜索做的 比多重背包快了很多

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int op=0;
int mid;
int a[8];
void dfs(int cnt,int sum)
{
    if(op)return;
    if(sum==mid)
    {
        op=1;
        return ;
    }
    for(int i=cnt; i>=1; i--)
    {
        if(a[i])
            if(sum+i<=mid)
            {
                a[i]--;
                dfs(i,sum+i);
            }
    }
}
int main()
{
    int count=0;
    while(1)
    {
        int sum=0;
        for(int i=1; i<=6; i++)
        {
            scanf("%d",&a[i]);
            sum+=i*a[i];
        }
        if(sum==0)break;
        printf("Collection #%d:\n",++count);
        if(sum%2==1)
        {
            printf("Can't be divided.\n\n");
            continue;
        }
        mid=sum/2;
        op=0;
        dfs(6,0);
        if(op)printf("Can be divided.\n\n");
        else  printf("Can't be divided.\n\n");

    }
    return 0;
}
posted @ 2016-04-25 20:45  -梦里不知身是客  阅读(365)  评论(0编辑  收藏  举报