题解摘自做题记录。
分析
数据范围明显得要让我们分开搞。
【Sub2】
应该是暴力。这里有个主体思路,我们完全可以贪心地将当前背包里的食材删掉,直到每种出现过的食材数量刚好为 。因为我们保留更多的是没有用的。那么我们就可以用二进制数表示 种食材的出现状态了。
同时,可能存在当前的一个状态 ,将 与第 个采集点结合时出现了背包装不下,单删掉 中的几个 后能够装下且更优。这启示我们,对于一个 实际上是可能转移到其一个子集会更优。既然都能转到子集了,那么在第 个采集点的时候,记 为这个采集点每个食材的出现状态,我们就完全可以用一个与 不交的状态 来转移。
我们对于当前能够达到的所有状态 去转移 。如果 已经被转移过了,那显然是没有必要再转移一次的。那么我们就能保证每个状态最多被转移 次。同时,因为 的所有子集也可以去转移,所以算上枚举子集的复杂度就是 的。
这里给个小优化:因为 十分巨大,如果我们对于每个 都去枚举它能达到的状态 ,最坏是 的,但是根据上一自然段的分析,得知对于相同的 是没必要再去遍历一遍的,直接清空就行。具体操作的时候会发现,我们可能一个 了,在这个采集点是无法转移的,而可能会有后面的某个转移点可以转移,但是我们给它清空了。为了避免这种情况,我们可以存一下 。
【Sub3】
考虑到,对于一个状态 ,如果它可以通过 和 得到,当且仅当 是 的子集。根据 Sub2 分析的第二个自然段,可以进一步得到:当状态 能被转移到时,需要满足 的所有子集都能被转移到。那么我们拿一个 set 来记录所有合法的状态,如果一个状态可以得到,我们去推它的一个超集,动态插入所有从不合法变成合法的超集。那么之后任意时间,这个状态都没有用了,可以直接删掉。
现在考虑枚举超集。根据上述的条件,我们得知 合法的前提是其子集都合法,那么我们枚举超集的时候就只需要枚举所有 的 的超集,只要 删掉任意一个 得到的集合都合法,那么它就合法了。为什么不需要枚举 的超集?很显然,当 且 是 的子集时,如果 仍不合法,那么 显然不合法。如果 合法,那么 将在枚举 的超集时被枚举到。所以这样就是对的。
因为这样我们保证了对于任意时刻,不存在 set 中的两个状态 ,有 是 的子集。所以 set 中最多 个状态。额,分析不来了。复杂度未知,应该不是很大。
代码
你可以自己写。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性