POJ 1014 Dividing (动态规划、多重背包)

这是一道典型的多重背包问题。刚开始写的时候就是用最简单的多重背包的解法,也就是将多重背包转化成01背包来求解,结果T了很多次。后来转化成完全背包和01背包来求解,不过没有用log的算法进行优化,还是t。最后只好使用log的优化来优化转化为01背包的问题。

知道了解法还是先说说思路吧。题目给了6种物品,每种物品的件数,然后问能否平分。我们把所有的物品看成价值和费用相同的物品,然后使用多重背包的算法就行求解,看一半的总的价值的背包容量能否正好装一半的价值。如果可以就是可以平分否则就是不能平分。

下面是ac代码供参考:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 70010
int dp[2*MAX];
int a[10];
int inline max(int a,int b)
{
    if(a>b) return a;
    else    return b;
}

int solve(int n,int v)
{
    int i,j,k,amount;
    memset(dp,0,sizeof(dp));
    for(i=1;i<=n;i++)
    {
        if(a[i]*i>=v)//完全背包
        {
            for(j=i;j<=v;j++)
                dp[j]=max(dp[j],dp[j-i]+i);
        }
        else//01背包
        {
            k=1;
            amount=a[i];
            while(k<amount)
            {
                for(j=v;j>=k*i;j--)
                    dp[j]=max(dp[j],dp[j-k*i]+k*i);
                amount-=k;
                k*=2;
            }
            for(j=v;j>=amount*i;j--)
                dp[j]=max(dp[j],dp[j-amount*i]+amount*i);
        }
    }
    return dp[v];
}

int main()
{
    int cas=0,flag,i,sum;
    while(1)
    {
        cas++;
        sum=0;
        for(i=1;i<=6;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i]*i;
        }
        flag=0;
        for(i=1;i<7;i++)
        {
            if(a[i]!=0)
            {
                flag=1;
                break;
            }
        }
        if(flag==0)
        {
            break;
        }
        if(sum%2==1)
        {
            printf("Collection #%d:\nCan't be divided.\n\n",cas);
            continue;
        }
        i=solve(6,sum/2);
        if(i==(sum/2))
            printf("Collection #%d:\nCan be divided.\n\n",cas);
        else
            printf("Collection #%d:\nCan't be divided.\n\n",cas);
    }
    return 0;
}


你可能感兴趣的:(优化,算法)