ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「小组联考」最优卡组

2019-10-23 20:53:44  阅读:314  来源: 互联网

标签:... 那么 卡组 状态 11111 ...... overline 最优 联考


题目

【内存限制:512 MiB】【时间限制:1000 ms】 【标准输入输出】【题目类型:传统】【评测方式:文本比较】

题目描述

$chitanda$ 有 $k$ 个卡包,第 $i$ 个卡包里有 $c_i$ 张卡,每张卡有一个能力值,其中第 $i$ 个卡包里的第 $j$ 张卡具有 $a_{i, j}$ 点能力值。
他准备选择 $k$ 张卡牌的组合,其中每个卡包要选择恰好一张卡牌。他希望这 $k$ 张卡牌的能力值之和尽量大,请你告诉他在所有可能的组合里,能力值之和最大的 $n$ 个组合分别具有多大的能力值。

输入格式

第一行包含两个整数 $k$ 和 $n$,含义见题目描述。
接下来 $k$ 行,每行描述一个卡包的信息,其中第 $i$ 行的第一个整数表示 $c_i$,接下来该行会有 $c_i$ 个整数,依次表示这个卡包里每张卡的能力值。

输出格式

输出一行,包含 $n$ 个整数,相邻两个数字之间用空格隔开,其中第 $i$ 个整数表示第 $i$ 大的能力值之和。

样例

样例输入
2 9
3 1 3 5
3 2 3 3
样例输出
8 8 7 6 6 5 4 4 3

样例解释

$chitanda$ 有 $3 \times 3$ 种选法,能力值分别为 $1 + 2, 1 + 3, 1 + 3, 3 + 2, 3 + 3, 3 + 3, 5 + 2, 5 + 3, 5 + 3$。

数据范围与提示

对于所有数据,$k \geq 2,$ $1 \leq n \leq \prod\limits_{i = 1}^{k}{c_i},$ $c_i \geq 1,$ $1 \leq a_{i, j} \leq 10^9$ $(i = 1, 2, \cdots, k; j = 1, 2, \cdots, c_i)$。

题解

做题经历

考试的时候想到一个很类似于正解的东西,预估时间复杂度 $O(nk)$ ,但是想到很多限制,结果代码都不敢码......

最后痛失 $50pts$ 。

接下来说一下这个思路吧。

$SUBSULOTION#50pts$

首先,我们先将每个卡组内的卡从大到小排个序。

然后,我们再定义一个数字串,定义不方便说,直接拿例子解释

有这样一个数字串:

数位: $12345$

数串: $13211$

这个数串表示的意思就是:在这种情况下,第一组取的是第一大的,第二组取的是第三大的,第三组取的是第二大的......以此类推

那么,毫无疑问,最大的能力值一定是 $11111$

然后呢?次大的呢?

我们不知道次大的是哪个,但是我们肯定可以保证次大在 $21111、12111、11211、11121、11112$ 中

我们把这些数串叫做子状态

那么这个思路就出来了:

把状态放进优先队列里面,每次取出最大的状态,输出,再放进它的子状态......重复 $n$ 次即可。

但是这样呢,每个状态会最多被放入 $k$ 次,为什么?

举个栗子:

状态 $23426$

它可能被 $13426、22426、23326、23416、23425$ 放进去。

那么时间复杂度大概是 $O(n\cdot k\cdot log)$

看看范围,还可以过一半,挺好......

正解

一道思路诡异的贪心题,但是这个思路也不是不可想,只是要分析到点上。

我们其实可以在 $50pts$ 的思路上加以改进。

首先,超时思路为什么会时间复杂度高?

是因为同一个状态被最多放进了 $k$ 次。


 

那么怎么解决这个问题呢?

这里有一个最终的解决方法,先说出来,然后解释其正确性以及如何思考。

首先,我们可以在输入的时候得到 $k$ 个串 $a_{i,j}$ 表示第 $i$ 组卡牌的能力值

将每个组内卡牌从大到小排序,然后设 $val_i=a_{i,1}-a_{i,2}$

具体意思就是 $val_i$ 表示第 $i$ 组中最大的牌减次大的牌的值

再按照 $val_i$ 从大到小把数组顺序重排

在处理完这些之后,我们来看怎么放进状态的子状态

设我们有一个状态 $\overline{×××...××××ab11111......11111}$

其中 $×$ 不用管,就是来占位置用的,而 $b$ 之前全是 $1$

那么我们会对这个状态做出三个转移,其中一个是特例:

  • 子状态一:$\overline{×××...××××a(b+1)11111......11111}$
  • 子状态二:$\overline{×××...××××ab21111......11111}$
  • 子状态三(仅当 $b=2$ 时):$\overline{×××...××××a(b-1)21111......11111}=\overline{×××...××××a121111......11111}$

最后把他们放入优先队列,同样地维护即可。

那么这样做有什么好处吗?

首先,它不会出现重复状态被压入优先队列。

为什么?

假设队列中有这样一个状态:$\overline{×××...××××ab11111......11111}$(注意不要和之前的状态混淆了)

如果 $b≥2$ 且当 $b=2$ 时 $a≠1$ ,那么它只有一个前驱 $\overline{×××...××××a(b-1)11111......11111}=\overline{×××...××××a111111......11111}$

但是如果 $b=2$ 且 $a=1$ 时,我们可以否决其前驱是 $\overline{×××...××××a(b-1)11111......11111}=\overline{×××...××××1111111......11111}$ ,这个很好想

那么它的祖先就有且只有 $\overline{×××...××××1211111......11111}$ ,就是那种特殊子状态

所以说,这样转移显然每种状态就只会出现一次

那么,它还有什么优势呢?

又来举同一个栗子,我们有状态 $\overline{×××...××××ab11111......11111}$

那么,当不是特殊情况时,我们的转移是 $\overline{×××...××××(a+1)b11111......11111}$ 或者是 $\overline{×××...××××a(b+1)11111......11111}$

那么,这两种状态。是否都比 $\overline{×××...××××(a+1)b11111......11111}$ 小呢?答案是肯定的。

但如果是特殊情况:$\overline{×××...××××2111111......11111}\Rightarrow \overline{×××...××××1211111......11111}$

这样转移的话,子状态是否也是比前驱状态小呢?

答案也是肯定的。

为什么?提示:这和我们开始时那个特别的排序也是有关的。

综上,这个处理方案有两点好处:

  • 状态唯一
  • 子状态大小有序

那么我们看一看,其时间复杂度是不会超过 $O(3nlog)$ 的。


但是又有一个问题:这个神仙思路是怎么想到的呢?

 

首先,对于 $50pts$ 的思路是一定要想到的,然后对于时间复杂度进行分析。 时间复杂度 $O(knlog)$ ,首先这个 $n$ 是一定跑不掉的,然后 $log$ 也肯定是有的,因为我们始终要用堆进行维护。 那么我们就要尽可能地将 $k$ 变小。 这个 $k$ 是跟子状态有关的,那么我们要尽可能减小子状态的数量。 那么,我们引入一个比较好想的思路:每次只更改第一个不是 $1$ 的位置 比如对于一个状态:$\overline{×××...××××ab11111......11111}$ 那么它的子状态就是 $\overline{×××...××××a(b+1)11111......11111}$ 或者 $\overline{×××...××××ab21111......11111}$ 但是有一种情况:$\overline{211...112}$,在我们的子状态定义中是够不到的。 所以还要再定义一个子状态:$\overline{×××...××××a(b-1)(1+1)111......11111}$,再普遍一点:$\overline{×××...××××(a-1)(b+1)1111......11111}$ 这样我们就可以从$211..1$ 到 $1211...11$ 到 $1121...11$ ....到 $1111...2$,把这种特殊情况包含进去 但是这样又会有一个问题了,举个栗子,状态 $232$ 可以通过状态 $241$ 得到,也可以通过 $231$ 得到,这样就重复了。 所以为了避免重复,我们只在 $a=1,b=2$ 时进行最后一次子状态下传。 而将 $a=1,b=2$ 转成 $a=2,b=1$ 的同时,又要保证先大后小,就加入了那个奇奇怪怪的排序方式。
$AC$ 思路就是这样,代码:
题解都打了那么多,代码却写不出来了......

 

标签:...,那么,卡组,状态,11111,......,overline,最优,联考
来源: https://www.cnblogs.com/MachineryCountry/p/11728008.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有