首页 > 其他分享 >HDU 1059 Dividing

HDU 1059 Dividing

时间:2024-03-20 21:01:15浏览次数:20  
标签:HDU Dividing int 1059 divided Collection 弹珠 new dp

题目传送门:Problem - 1059 (hdu.edu.cn)

问题描述

玛莎和比尔拥有一些弹珠。他们希望在自己之间分配收藏品,以便双方都获得平等的弹珠份额。如果所有弹珠都具有相同的价值,这将很容易,因为这样他们就可以将收藏品分成两半。但不幸的是,有些弹珠比其他弹珠更大或更漂亮。因此,Marsha 和 Bill 首先为每颗弹珠分配一个值,一个介于 1 到 6 之间的自然数。现在他们想把弹珠分开,这样每个弹珠都得到相同的总价值。
不幸的是,他们意识到以这种方式划分弹珠可能是不可能的(即使所有弹珠的总价值是偶数)。例如,如果有一个值为 1 的弹珠、一个值为 3 的弹珠和两个值为 4 的弹珠,则不能将它们拆分为相等值的集合。因此,他们要求您编写一个程序来检查弹珠是否存在公平的分区。   输入 输入中的每一行都描述了一个要分割的弹珠集合。这些线由六个非负整数 n1、n2、...、n6 组成,其中 ni 是值为 i 的弹珠数。因此,上面的示例将由输入行“1 0 1 2 0 0”描述。弹珠的最大总数为 20000 个。

输入文件的最后一行将是 ''0 0 0 0 0 0'';不要处理此行。   输出 对于每个 colletcion,输出 ''Collection #k:“'',其中 k 是测试用例的编号,然后是 ''Can be divided.' 或 ''Can't be divided.''。

在每个测试用例后输出一个空行。  

样本输入


1 0 1 2 0 0 


1 0 0 0 1 1 


0 0 0 0 0 0



 

示例输出


Collection #1: Can't be divided. 



Collection #2: Can be divided.


题目大意:有6种不同大小的弹珠,价值依次为1-6。现在给你一些这些不同种类的弹珠,让你进行分配,使两个人手上的弹珠价值之和相同,一个弹珠不能划分。

题解思路·:读题发现这是一个多重背包问题,最多20000个弹珠,总价值可能为6*20000,直接三重循环暴力dp肯定会超时,考虑用二进制拆分来写

直接上代码:

#include <iostream>
#include <cstring>
using namespace std;
const int N = 20010;
int n, c; // n原有物品总价值
int v[N], m[N];
int new_n;    // 二进制拆分后的新物品总数量
int new_v[N]; // 拆分后新物品的价值
int dp[N];

int main()
{
    int t = 0;
    while (cin >> m[1] >> m[2] >> m[3] >> m[4] >> m[5] >> m[6])
    {
        memset(dp, 0, sizeof dp);
        t++;
        n = 0, new_n = 0;
        for (int i = 1; i <= 6; i++)
        {
            n += m[i] * i;
            v[i] = i;
        }
        if (n == 0)
            break;
        if (n & 1) // 如果总价值为奇数,必定不可平分
        {
            printf("Collection #%d:\nCan't be divided.\n", t);
            cout << endl;
            continue;
        }
        n /= 2;
        c = n;
        for (int i = 1; i <= 6; ++i)
        {
            for (int j = 1; j <= m[i]; j <<= 1) // 二进制枚举:1,2,4,...
            {
                m[i] -= j;                 // 减去已拆分的
                new_v[++new_n] = j * v[i]; // 新物品价值
            }
            if (m[i]) // 余数
                new_v[++new_n] = m[i] * v[i];
        }

        // 01背包(滚动数组版)
        for (int i = 1; i <= new_n; ++i)        // 枚举物品
            for (int j = c; j >= new_v[i]; --j) // 枚举价值(容量)
                dp[j] = max(dp[j], dp[j - new_v[i]] + new_v[i]);
        if (dp[c] == n)
            printf("Collection #%d:\nCan be divided.\n", t);
        else
            printf("Collection #%d:\nCan't be divided.\n", t);
        cout << endl;
    }

    return 0;
}

收获:

二进制拆分模板:

int new_n = 0;
for (int i = 1; i <= 6; ++i)
  {
     for (int j = 1; j <= m[i]; j <<= 1)//二进制枚举:1,2,4,...
        {
            m[i] -= j;//减去已拆分的
            new_v[++new_n] = j * v[i];//新物品价值
            new_w[new_n] = j * w[i];
         }
     if (m[i])//余数
        {
            new_v[++new_n] = m[i] * v[i];
            new_w[new_n] = j * w[i];
        }

  }

标签:HDU,Dividing,int,1059,divided,Collection,弹珠,new,dp
From: https://blog.csdn.net/2302_81939382/article/details/136888067

相关文章

  • HDU 2048:神、上帝以及老天爷(错排问题)
    一、原题链接[Problem-2048(hdu.edu.cn)](https://acm.hdu.edu.cn/showproblem.php?pid=2045)二、题面HDU2006'10ACMcontest的颁奖晚会隆重开始了!为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的:首先,所有参加晚会的人员都将一......
  • HDU 2045:不容易系列之(3)—— LELE的RPG难题(动态规划)
    一、原题链接Problem-2045(hdu.edu.cn)二、题面人称“AC女之杀手”的超级偶像LELE最近忽然玩起了深沉,这可急坏了众多“Cole”(LELE的粉丝,即"可乐"),经过多方打探,某资深Cole终于知道了原因,原来,LELE最近研究起了著名的RPG难题:有排成一行的n个方格,用红(Red)、粉(Pink)、绿(G......
  • HDU 2036:改革春风吹满地(多边形面积计算)
    一、原题链接Problem-2036(hdu.edu.cn)参考:如何编程计算任意多边形的面积?理解了之后发现好简单!_哔哩哔哩_bilibili二、题面“改革春风吹满地,不会AC没关系;实在不行回老家,还有一亩三分地。谢谢!(乐队奏乐)”话说部分学生心态极好,每天就知道游戏,这次考试如此简单的题......
  • HDU 2056:Rectangles(两个矩形交点的性质)
    一、原题链接Problem-2056(hdu.edu.cn)二、题面Giventworectanglesandthecoordinatesoftwopointsonthediagonalsofeachrectangle,youhavetocalculatetheareaoftheintersectedpartoftworectangles.itssidesareparalleltoOXandOY.三、......
  • [HDU6647] Bracket Sequences on Tree 题解
    [HDU6647]BracketSequencesonTree题解一道纯靠自己推出来的换根\(dp+\)树哈希,写篇题解庆祝一下~~题意:给定一棵无根树,你可以任意选择根节点和遍历顺序,每次遍历时进入一个节点就标记一个(,离开一个节点就标记一个),问所有存在的括号序列有多少种,对998244353取模。先考虑根固......
  • 手把手教你免费用Flashduty做消息通知
    为什么需要消息通知?如果有重要的情况发生,希望能通过各种媒介通知我们。可以举几个例子:家里燃气费没有了,希望能有短信或者app通知api频繁500报错,希望及时感知,及时修复公司网站是https自签名证书,为了保证可用性,每天会有e2e测试保证证书的有效性,如果过期及时通知为什么不用腾......
  • 【题解】「HDU 7084」Pty loves string
    CQBZOJHDU7084不难想到把最终在\(S\)从中间分开,就变成了前后两个broder拼起来。考场重现:直接把所有的broder求出来,将相同长度的broder的下标存在一起,然后暴力匹配,最后还没来及优化。考场代码(除了fail树,其她其实都挺逼近正解正解是建出fail树(甚至搞忘还有这东......
  • UOJ228/HDU5828 基础数据结构练习题/Rikka with Sequence 题解(势能线段树)
    势能线段树。如果线段树上一个节点的\(\max-\min\ge2\),我们称其为关键节点,考虑定义势能\(\phi\)为线段树上关键节点的个数。对于每次开方操作,如果当前节点为关键节点,则暴力递归左右儿子修改,否则:如果当前节点\(\max=\min\)或\(\max=\min+1\)且\(\max\)不是完全平方数,......
  • [ARC133B] Dividing Subsequence
    DividingSubsequence这道题与最长公共子序列类似,可以先去水一水那道题。题意本题就是让你从\(p\)里面选出一个子序列\(b_i\)和\(q\)里面选出一个子序列\(a_i\),我们要使\(b_i\)是\(a_i\)的倍数。解法本题直接用动态规划,是\(O(n^2)\)做法,会超时,因此我们用树状数......
  • hdu5213
    我们看到双区间询问,可以想一下怎么转换成单区间询问这个用容斥原理写也非常简单\(f(L,V)\)指的是\(f(L,U-1)\)和\(f(R+1,V)\)指的是会发现中间被多减了一次,所以加回来有\(f(R+1,U-1)\)于是就转换成了单区间询问题目没有对序列进行修改,所以可以离线处理所有询问,使用莫队算......