有两个小朋友想要平分一大堆糖果,但他们不知道如何平分需要你的帮助,由于没有spj我们只需回答能否平分即可。

糖果大小有6种分别是1、2、3、4、5、6,每种若干颗,现在需要知道能不能将这些糖果分成等额的两堆。

一颗大小为6的糖果,可以相当于2颗大小为3的糖果,其他同理,即大小满足加法,但是1颗糖果是不能被拆分的。

Input

多组输入,每行输入6个非负整数,分别表示大小为1、2、3、4、5、6的糖果的数量,若输入6个0代表输入结束。

单种糖果的数量不会超过20000。

Output 每组询问先输出一行 "Collection #k:",k表示第几组询问。

再输出一行表示答案,若能分割,输出 “Can be divided.”,若不能输出 ”Can't be divided.“

每组输出后空一行

Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
Sample Output
Collection #1:
Can't be divided. Collection #2:
Can be divided.

思路

  • 题意: 给我们6种物品,每种物品有各自的数量,第i种物品的价值、与所占的空间均是i,能否将将这个六种物品的价值均分为两份
  • 分析:1.如果6种物品价值之和sum为奇数,显然不可能均分;否则的有可能均分,那么我们把 \(sum/2\)作为的背包的空间,如果我们在dp之后, \(dp[sum/2] == sum/2\), 说明用 sum/2的空间是可以均分的。
  • 代码1:我是把完全背包转01背包了,这样同种物品就转化为了不同的物品,不过显然由于每种的物品数量太多肯定会T
  • 代码2: 则是把完全背包的 每种物品进行 “二进制拆分”这样拆分之后的物品数量就像对于代码1的转化方法大大的减少了

代码一(完全背包转01背包--->T了)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int Len = 200000;
int ar[7], dp[Len]; int main()
{
/* freopen("A.txt","r",stdin); */
int Case = 1;
while(scanf("%d %d %d %d %d %d", &ar[1], &ar[2], &ar[3], &ar[4], &ar[5], &ar[6]) && ar[1] + ar[2] + ar[3] + ar[4] + ar[5] + ar[6])
{
int sum = ar[1]*1 + ar[2]*2 + ar[3]*3 + ar[4]*4 + ar[5]*5 + ar[6]*6;
if(sum % 2)
{
printf("Collection #%d:\nCan't be divided.\n\n", Case ++);
continue;
} sum /= 2;
for(int i = 0; i <= sum; i ++)
dp[i] = 0; for(int i = 1; i <= 6; i ++) //把多重背包拆分成一个一个的01背包
for(int j = 1; j <= ar[i]; j ++)
for(int k = sum; k >= ar[i]; k --)
dp[k] = max(dp[k], dp[k - i] + i);
if(dp[sum] == sum)
printf("Collection #%d:\nCan be divided.\n\n", Case ++);
else
printf("Collection #%d:\nCan't be divided.\n\n", Case ++);
} return 0;
}

代码二(完全背包--->二进制优化)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int Len = 200000;
int ar[7], dp[Len], w[Len]; int main()
{
/* freopen("A.txt","r",stdin); */
int Case = 1;
while(scanf("%d %d %d %d %d %d", &ar[1], &ar[2], &ar[3], &ar[4], &ar[5], &ar[6]) && ar[1] + ar[2] + ar[3] + ar[4] + ar[5] + ar[6])
{
int sum = ar[1]*1 + ar[2]*2 + ar[3]*3 + ar[4]*4 + ar[5]*5 + ar[6]*6;
if(sum % 2)
{
printf("Collection #%d:\nCan't be divided.\n\n", Case ++);
continue;
} //把某个物品有多个的进行二进制拆分
int cnt = 1;
for(int i = 1; i <= 6; i ++)
{
for(int j = 1; j <= ar[i]; j <<= 1)
w[cnt ++] = j * i, ar[i] -= j;
if(ar[i]) //注意:这个地方剩余的数,不要忘了添加上去!
w[cnt ++] = ar[i] * i;
} sum /= 2;
for(int i = 0; i <= sum; i ++)
dp[i] = 0; for(int i = 1; i < cnt; i ++) //把通过二进制优化以后,就变成了一个简单的背包问题了
for(int k = sum; k >= w[i]; k --)
dp[k] = max(dp[k], dp[k - w[i]] + w[i]);
if(dp[sum] == sum)
printf("Collection #%d:\nCan be divided.\n\n", Case ++);
else
printf("Collection #%d:\nCan't be divided.\n\n", Case ++);
} return 0;
}

D - D 分糖果HDU - 1059(完全背包+二进制优化)的更多相关文章

  1. HDU 3591 (完全背包+二进制优化的多重背包)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3591 The trouble of Xiaoqian Time Limit: 2000/1000 M ...

  2. hdu 2191 (多重背包+二进制优化)

    Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品, ...

  3. hdu 1171 Big Event in HDU(多重背包+二进制优化)

    题目链接:hdu1171 思路:将多重背包转为成完全背包和01背包问题,转化为01背包是用二进制思想,即件数amount用分解成若干个件数的集合,这里面数字可以组合成任意小于等于amount的件数 比 ...

  4. hdu 2191 (多重背包二进制优化)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191 实现代码: #include<bits/stdc++.h> using namespac ...

  5. hdu 2844 多重背包二进制优化

    //http://www.cnblogs.com/devil-91/archive/2012/05/16/2502710.html #include<stdio.h> #define N ...

  6. HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)

    HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...

  7. HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)

    HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...

  8. HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化)

    HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化) 题意分析 首先C表示测试数据的组数,然后给出经费的金额和大米的种类.接着是每袋大米的 ...

  9. hdu1059 多重背包(转换为01背包二进制优化)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1059 之前写过一个多重背包二进制优化的博客,不懂请参考:http://www.cnblog ...

随机推荐

  1. java编写非对称加密,解密,公钥加密,私钥解密,RSA,rsa

    非对称加密已经被评为加密标准,主要包含(公钥加密私钥解密,或者私钥加密公钥解密)本文主要讲解的是如何用java生成 公钥和私钥并且 进行字符串加密 和字符串解密    //如需要代码copy如下 im ...

  2. JavaScript(js)函数声明与函数表达式的区别

    在JavaScript中,函数是经常用到的,在实际开发的时候,我想很多人都没有太在意函数的声明与函数表达式的区别,但是呢,这种细节的东西对于学好js是非常重要的. 函数声明与函数表达式用代码写出来是这 ...

  3. Excel之在单元格中生成随机密码

    公式 =CHAR(INT(RAND()*26+97))&INT(RAND()*10)&CHAR(INT(RAND()*26+97))&INT(RAND()*10) 分析 CHA ...

  4. 程序员过关斩将-- 喷一喷坑爹的面向UI编程

    摒弃面向UI编程 为何喷起此次话题,因为前不久和我们首席架构师沟通,谈起程序设计问题,一不小心把UI扯进来,更把那些按照UI来编程的后台工程师也扯了进来.今天特意百度了一下(其实程序员应该去googl ...

  5. SpringBoot——Cache使用原理及Redis整合

    前言及核心概念介绍 前言 本篇主要介绍SpringBoot2.x 中 Cahe 的原理及几个主要注解,以及整合 Redis 作为缓存的步骤 核心概念 先来看看核心接口的作用及关系图: CachingP ...

  6. SpringBoot2整合Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the calling code 【已解决】

    SpringBoot集成Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the callin ...

  7. python读取文件指定行内容

    python读取文件指定行内容 import linecache text=linecache.getline(r'C:\Users\Administrator\Desktop\SourceCodeo ...

  8. Docker基本概念及架构

    一.Docker基本概念 Docker是一个开源的容器引擎,基于Go 语言并遵从 Apache2.0 协议开源.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布 ...

  9. flex 居中

    display: flex; justify-content: space-between; align-items: center;

  10. channel的基本使用

    1.管道分类 读写管道 只读管道 只写管道 缓冲通道 :创建时指定大小(如果不指定默认为非缓冲通道) 2.正确使用管道 管道关闭后自能读,不能写 写入管道不能超过管道的容量cap,满容量还写则会阻塞 ...