• 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:
    ",cns);
    34         if(sum & 1)
    35         {
    36             printf("Can't be divided.
    
    ");
    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.
    
    ":"Can't be divided.
    
    "); 
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    教你透彻了解红黑树(转)
    算法描述伪代码
    B 树、B+ 树、B* 树
    Java四种引用类型
    Java程序以后台方式在Linux上运行(nohup命令)
    java 文档注释
    Reactor模式和NIO
    Immutable模式与string类的实现
    mina 入门
    索引和优化查询
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7725512.html
Copyright © 2020-2023  润新知