POJ 1014 Dividing

同HDU 1059 细节见这里

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define MAX_N 210005   //最多20000件

int marblenum[7], marblevalue[7]={0,1,2,3,4,5,6},
    dp[MAX_N+1], a[200];
int main()
{
    int testnum = 0;
    while(scanf("%d%d%d%d%d%d",&marblenum[1],&marblenum[2],&marblenum[3],&marblenum[4],&marblenum[5],&marblenum[6]))
    {
        int flag = 0, sum = 0;
        for(int i = 1;i < 7;i++)
        {
            if(marblenum[i]!=0)
            {
                flag = 1;
                sum += marblenum[i] * i;
            }
        }


        if(flag)
        {
            testnum++;
            if(sum % 2 != 0)
            {
                printf("Collection #%d:\nCan't be divided.",testnum);
            }

            else //可以整除的情况
            {
                int contain = sum / 2,cnt = 0;
                for(int i = 1;i <= 6;i++)//遍历每一种
                {
                    //按规律分堆
                    for(int j = 1;j <= marblenum[i];j *= 2)//n+1>2^k 2^j <= n 相当于 2^j < n+1
                    {
                        a[++cnt] = i*j; //生成的这一堆的价值
                        marblenum[i] -= j; //用掉多少就减去多少
                    }
                    if(marblenum[i] != 0) //没有完全用光
                        a[++cnt] = i*marblenum[i]; //额外放一堆
                }
                memset(dp, 0, sizeof(dp));



                //此时转化为01背包 已经拥有cnt种物品 每件一个 最大容量contain
                for(int i = 1;i <= cnt;i++)
                {

                    for(int j = contain;j >= a[i];j--)
                    {
                        dp[j] = max(dp[j],dp[j-a[i]]+a[i]);
                    }
                }



                if(dp[contain]!=contain)
                {
                    printf("Collection #%d:\nCan't be divided.", testnum);
                }
                else
                {
                    printf("Collection #%d:\nCan be divided.", testnum);
                }
            }
            printf("\n\n");
        }


        else //全部为0 结束输入
        {
            break;
        }
    }
    return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值