微信扫一扫打赏支持

P1537 弹珠

P1537 弹珠

题目描述

玛莎和比尔各自有自己的弹珠收藏。他们想重新分配收藏品,使两人能平等拥有弹珠。如果所有的弹珠的价值相同,那么他们就可以平分。但不幸的是,有一些弹珠更大,或者更美丽,所以,玛莎和比尔给每个弹珠一个1到6的价值。现在他们想平分这些弹珠,使每个人得到的总价值相同。不幸的是,他们发现,他们可能无法以这种方式分弹珠(即使弹珠的总价值为偶数)。例如,如果有一个价值为1、一个价值为3和两个价值为4的弹珠,这样他们就不能把弹珠分为价值相等的两部分。因此,他们想要你写一个程序,告诉他们是否能将所有弹珠分成价值相等的两部分。

输入输出格式

输入格式:

 

输入文件有若干行,行中包含六个非负整数N1,。..,N6,其中mi是数值i的弹珠的价值。最大弹珠总数将达到20000。

输入文件的最后一行是0 0 0 0 0 0 。不要处理这一行。

 

输出格式:

 

对于每一组数据,输出"Collection #k:", k为输出的是第几组, 接着是"Can be divided." 或 "Can't be divided.".

每一组输出后多打一个空行。

 

输入输出样例

输入样例#1: 复制
1 0 1 2 0 0 
1 0 0 0 1 1 
0 0 0 0 0 0 
输出样例#1: 复制
Collection #1:
Can't be divided.

Collection #2:
Can be divided.

 

 

洛谷题解:

整个题目的思路其实就是多重背包,背包容量是所有弹珠美丽总和的一半

我们可以先记录出所有弹珠的美丽总和,如果是奇数,那么一定不能平均分成两份(这个题目里有暗示)然后我们进行dp就行了

注意事项:

1.多重背包的二进制优化问题,可以节省大量时间,二进制优化实际将多重背包转化成01背包,意思是假如某个物体数量是13,那么

我们把它拆成1,2,4,6,四个物体 进行dp就能表示出这一种物体所有不同的取得的状态

2.背包压维。

3.多组数据要清空数组。

然后 状态表示:dp【j】 表示 能否取得美丽总和为j的弹珠

     转移方程::dp[j] = dp[j] || dp[j - stack[i]];

 

弄清楚dp是怎样进行枚举的:

普通的背包问题的二维表的枚举方式

 

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int dp[20001];
 5 int stack[120001];
 6 int top = 0;
 7 int num[7];
 8 int sum = 0;
 9 int main()
10 {
11     int cns = 0;
12     while("Zuo Zhe is handsome")
13     {
14         cns ++;
15         top = 0;
16         sum = 0;
17         for(int i = 1;i <= 6;i ++)
18         {
19             int wei;
20             scanf("%d",&wei);
21             sum += wei * i;
22             int zz = 1;
23             while(wei >= zz)
24             {
25                 stack[++ top] = zz * i;
26                 wei -= zz;
27                 zz *= 2;
28             }
29             if(wei)
30               stack[ ++ top] = wei * i;
31         }
32         if(top == 0)break;
33         printf("Collection #%d:\n",cns);
34         if(sum & 1)
35         {
36             printf("Can't be divided.\n\n");
37             continue;
38         }
39         sum /= 2;
40         memset(dp,0,sizeof(dp));
41         dp[0] = 1;
42         for(int i = 1;i <= top;i ++)
43         {
44             for(int j = sum;j >= stack[i];j --)
45              {
46               dp[j] = dp[j] || dp[j - stack[i]];
47             } 
48         }
49         printf(dp[sum] ?"Can be divided.\n\n":"Can't be divided.\n\n"); 
50     }
51     return 0;
52 }

 

posted @ 2017-10-24 20:15  范仁义  阅读(397)  评论(0编辑  收藏  举报