前言
参数一多脑子就睡觉
阿达西捧油, 你滴脑子浆糊一样的时候, 不妨听一下雄鹰一样男人的话
思路
首先分析问题, 发现这个背包看起来比较的恐怖, 于是我赛时弃掉了背包做法, 并且死活找不到 \(c_i \mid c_{i + 1}\) 怎么用
赛后发现其实分析问题做的还行, 找性质就很不对了
首先是这种倍数性质有一种不定进制数的感觉, 后面我就在这个基础上处理
首先抛开恰好 \(k\) 个不谈, 只考虑 \(p\) 的约束
因为可行性 \(\rm{dp}\) 注定不能解决, 我们考虑贪心
不难发现由于不定进制数的性质, 我们可以贪心的把 \(p\) 放到高位, 这样一定能保证最小的硬币数, 并且如果有合法解, 通过这种方法也一定能构造出来
具体解释一下, 任何一种合法解在收起来之后必定是这样的, 逆向来讲就是把可以把这样的放置方法拆分成任意合法解
下面称这种贪心方法构造的序列为「起始序列」, 各位记为 \(s_i\)
然后考虑 \(k\) 的约束, 本质上是找到上面的「起始序列」的一个最优拆分 \(h\), 使得恰好拆成 \(k\) 个, 并且要求 \(\sum h_iw_i\) 取到最值
因为 \(n, k\) 相比于 \(p, w_i\) 小很多, 于是不难发现 \(k\) 的约束可以状态维护, 但是 \(w_i\) 必须和 \(p\) 一样找点性质
什么时候 \(\sum h_iw_i\) 取到最值, 发现并不好直接处理, 但是发现一个关键性质
倘若我们取前 \(r\) 类硬币的时候已经使得 \(\sum h_iw_i\) 取到最值, 那么在这个基础上一定得到后面的最值
于是可以把它丢进 \(\rm{dp}\) 里维护
具体设计状态考虑 \(f_{i, j, l}\) 表示考虑前 \(i\) 类硬币, 已经拆成了 \(j\) 个硬币, \(c_i\) 硬币还有 \(l\) 个的最值 \(\sum h_iw_i\) 可以简单做到 \(\mathcal{O} (n k^2)\)
具体的, 考虑枚举当前到底拆了多少 \(c_i\) 给 \(c_{i - 1}\), 然后简单后缀 \(\min\) 维护即可
更具体的官方题解
- 状态定义: 表示处理到第 种硬币时,总硬币数为 ,且当前剩余 个 -面额硬币的最小重量。
- 状态转移:拆分 个 -面额硬币为 个 -面额硬币:
- 复杂度:状态数 ,总时间 。
输出结果
• 最小重量为 ,若无解则输出 -1
。
• 最大重量可通过符号翻转后相同算法求得。
总结
- 考察状态设计
- 不能用状态维护的问题
- 固定序列
- 贪心
- 拥有贪心性质的状物, 可以丢进 \(\rm{dp}\) 里维护\((\)但是不是状态\()\)
- 前后不相关的序列取数
- 拥有贪心性质的状物, 可以丢进 \(\rm{dp}\) 里维护\((\)但是不是状态\()\)
- 能用状态维护的
- 直接用状态维护并和上面结合
- 不能用状态维护的问题