Problem Description
Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value. 
Unfortunately, they realize that it might be impossible to divide the
marbles in this way (even if the total value of all marbles is even).
For example, if there are one marble of value 1, one of value 3 and two
of value 4, then they cannot be split into sets
of equal value. So, they ask you to write a program that checks whether
there is a fair partition of the marbles.
 
 Input
Each line in the input describes one
collection of marbles to be divided. The lines consist of six
non-negative integers n1, n2, ..., n6, where ni is the number of marbles
of value i. So, the example from above would be described
by the input-line ``1 0 1 2 0 0''. The maximum total number of marbles
will be 20000. 
The last line of the input file will be ``0 0 0 0 0 0''; do not process this line.
 
 Output
For each colletcion, output
``Collection #k:'', where k is the number of the test case, and then
either ``Can be divided.'' or ``Can't be divided.''. 
Output a blank line after each test case.
 
 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石头价值分别为1~6,现在给你这6种石头的个数,问你能否把它们分为价值相等的两堆。
  第一遍读完题觉得这是一个多重背包,准备模板直接过,但是看了看数据的范围,石头的个数能达到20000!铁铁的TLE。所以网上有学了一招----多重背包的二分优化。
  我们先来回顾一下,多重背包的本质还是01背包,01背包的本质是什么呢?我个人感觉就是把每种物品是否装进背包的情况遍历一遍。
  现在我们来看这样的问题,给你20个价值为1的物品,如果按照01背包的思路就要把这20个物品挨个判断是否加入背包。如果我们按照二进制的想法呢?
将这20个物品合并成1(2^0),2(2^1),4(2^2),8(2^3),5(20-1-2-4-8=5)这5个物品,只对这四个物品进行是否加入背包的判断是不是就大大减少了复杂度?现在问题转化为这两种背包是否等价?也就是用1,2,4,8,5这5个数能否组合出1~20里所有的数?  答案是显然可以的!前面2^n部分可利用二进制来表示1~15,从11到15上再加上那个5,就能表示16~20。如此,我们把个数较多的石头按2^n进行合并,最后剩下的单独一个(例如上面的5),这就是多重背包的二进制优化。
代码如下 :
 #include <bits/stdc++.h>

 using namespace std;
int num[],sum,v,cnt,i,j;
bool dp[];//dp[i]表示容量为i的背包能否装满
int main()
{
//freopen("de.txt","r",stdin);
int casenum=;
while ()
{
memset(dp,,sizeof dp);
memset(num,,sizeof num);
sum=;
for (i=;i<=;++i)
{
scanf("%d",&num[i]);
sum+=i*num[i];
}
if (sum==)
break;
printf("Collection #%d:\n",casenum++);
if (sum%)//如果所有石头总价值和为奇数肯定不能均分
{
printf("Can't be divided.\n\n");
continue;
}
else
{
v=sum/;//用总价值的一半来作为背包的容量
dp[]=;
for (i=;i<=;++i)
{
if (num[i]==)
continue;
for (j=;j<=num[i];j*=)//j来作为2^n的单位
{
cnt=i*j;
for (int k=v;k>=cnt;--k)
{
if (dp[k-cnt])//只有k-cnt的背包被装满,k的背包才能被装满
dp[k]=;
}
num[i]-=j;//分完2^n剩下的个数
}
cnt=num[i]*i;
if (cnt)
{
for (int k=v;k>=cnt;--k)
{
if (dp[k-cnt])
dp[k]=;
}
}
}
if (dp[v])//容量为v的背包能否被装满
printf("Can be divided.\n\n");
else
printf("Can't be divided.\n\n");
}
}
return ;
}
 

最新文章

  1. C#计算代码执行时间
  2. Python之路第一课Day9--随堂笔记之一(堡垒机实例以及数据库操作)未完待续....
  3. Get和Post区别
  4. android 布局学习
  5. IIS 部署 node.js ---- 基础安装部署
  6. dlmalloc(Android bionic C库的malloc实现)简介
  7. java 堆栈分析
  8. 修改Tomcat服务器的端口号
  9. Azure Remote Desktop: &quot;An error occurred while loading from file *.rdp&quot;
  10. mediastream2使用指南(转载)
  11. [Java Basics] Stack, Heap, Constructor, I/O, Immutable, ClassLoader
  12. Mongo客户端MongoVUE的基本使用
  13. UVa 1658 (拆点法 最小费用流) Admiral
  14. 关于Windows下如何查看端口占用和杀掉进程
  15. js正则表达式匹配字符串与优化过程
  16. HTML5 LocalStorage 本地存储总结
  17. Maven - 实例-2-使用本地仓库中的依赖包
  18. Windows10 Compatibility Telemetry(CompatTelRunner.exe) 占用硬盘100%
  19. 我遇到了Hibernate异常
  20. springmvc 请求无法到达controller,出现404

热门文章

  1. JDBC调用oracle 存储过程
  2. JS中字符串的常见属性及方法
  3. 20180914-Java实例03
  4. BZOJ 3687: 简单题(dp+bitset)
  5. 初步认识pug
  6. [TensorFlow 2] [Keras] fit()、fit_generator() 和 train_on_batch() 分析与应用
  7. HTTP返回码中200,302,304,404,500得意思
  8. Linux基本常用命令|ubuntu获取root权限
  9. QC OTA
  10. Java并发AtomicLongArray类