hdu 1023 背包

简单背包,不过直接背包会超时,需要将每一种物品个数转化一下,方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]13,就将这种 物品分成系数分别为1,2,4,6的四件物品。

代码如下:

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int coin[7],res[60000],value[10000],N;
int change(int a,int n)
{
    int k=1;
    if(n==0) return 0;
    do
    {
        n-=k;
        value[N++]=k*a;
        k=k<<1;
    }while(n>=k);
    if(n>0) value[N++]=n*a;
    return N;
}
int main()
{
    int i,j,count=0,sum;
    while(scanf("%d %d %d %d %d %d",&coin[1],&coin[2],&coin[3],&coin[4],&coin[5],&coin[6]))
    {
        if(coin[1]+coin[2]+coin[3]+coin[4]+coin[5]+coin[6]==0) break;
        sum=0; N=0; count++;
        for(i=1;i<=6;i++)
        {
            sum+=coin[i]*i;
            change(i,coin[i]);
        }
        if(sum%2==1) 
        {
            printf("Collection #%d:\nCan't be divided.\n\n",count);
            continue;
        }
        memset(res,0,sizeof(res));
        res[0]=1;
        for(i=0;i<N;i++)
            for(j=sum/2;j-value[i]>=0;j--)
                if(res[j-value[i]]) res[j]=1;
        if(res[sum/2]) 
            printf("Collection #%d:\nCan be divided.\n\n",count);
        else 
            printf("Collection #%d:\nCan't be divided.\n\n",count);
    }
    return 0;
}

 

 

 

 

posted @ 2012-04-20 11:06  书山有路,学海无涯  阅读(463)  评论(0编辑  收藏  举报