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 }
版权申明:欢迎转载,但请注明出处
一些博文中有一些参考内容因时间久远找不到来源了没有注明,如果侵权请联系我删除。
在校每年国奖、每年专业第一,加拿大留学,先后工作于华东师范大学和香港教育大学。
2024-10-30:27岁,宅加太忙,特此在网上找女朋友,坐标上海,非诚勿扰,vx:fan404006308
AI交流资料群:753014672