1 用两个元素的交换来推出贪心方法(邻项交换法)
这个方法适用于解决顺序问题或者安排问题,通过先解决小问题来总结出规律,从而解决出这个题目。
例题:P1080 [NOIP 2012 提高组] 国王游戏
这个题目就是典型的邻项交换法推贪心。
1. 假设
我们先假设国王后面只有两个大臣,而且假设国王拿着的是 ,第一个大臣拿的是 ,第二个大臣拿的是 ,我们有两种顺序。
-
第一个大臣在前面,那么第一个大臣得到的奖金就是 ,第二个大臣拿到的奖金就是 ,最高的奖赏就是 。
-
第二个大臣在前面,那么第二个大臣得到的奖金就是 ,第一个大臣拿到的奖金就是 ,最高的奖赏就是 。
2. 推导
现在我们就要来比较最高的奖赏,即比较 和 谁更小。
我们发现 一定小于等于 (因为 是大于 0 的整数,即 ,不会变小),同理 一定小于等于 。所以我们可以将式 转化为求 的答案。
我们把 和 同时除 ,在乘上 ,就把这两个式子化简为 和 。发现什么没有?我们把结果的大小比较转化为了大臣手上数的乘积比较,如果 小于 ,那么就把 1 号大臣排在前面,否则排在后面。
例题:P1248 加工生产调度
1. 假设
我们假设有两个产品 和 , 产品在 A 车间加工时间是 ,同理,其他的分别为 、、。
-
产品先做,那么 产品所有的时间就是 ,由于 产品要等到 产品加工完才行,那么 产品在 A 车间加工就需要 的时间( 的等待时间),而此时 产品在 B 车间加工了 的时间,还需要 的时间加工,所以 产品在 B 车间需要 的时间加工。由于 产品肯定是等到 产品加工后才结束,所以花费的总时间是 的时间。
-
同理 产品先做就需要花费 的时间。
2. 推导
现在我们需要比较 产品先做和 产品先做的时间,即求出
不难发现 ,对于 也成立,所以 式就可以化简为:
至于继续的推导,需要用到 Johnson 定理,感兴趣的读者可以自己去了解一下。
最终的排序方法是将 的 排前面。
例题:P1842 奶牛玩杂技
1. 假设
假设有两头牛 和 ,那么它们的体重分别是 和 ,力量是 和 。
如果现在只有这两头牛,那么:
-
在上面,那么 的压扁指数为 , 的压扁指数为 ,总压扁指数为 。(注意这里不能直接省去 ,虽然它为负数,但当 时就会取 。)
-
在上面,那么同理,总压扁指数为 )。
2. 进一步的假设
如果我们要使 在上面,那么我们该怎么做呢?
我们需要满足 。
易证 所以 就可以变为 ,同理 变为 。
因为我们要使 ,简单移项便可以得到 。
所以如果要使 在上面,必须要 。
2 区间类贪心(区间类问题)
这个方法适用于一系列的区间取舍问题,最基础的问题有:
- 区间选点(在 个区间放尽量少的点,使得每个区间都有点)
- 区间覆盖(选择尽量少的区间覆盖整个线段)
- 区间分组(将区间分成尽量少的组使得组内的区间两两互不相交)
区间类问题的常用方法是按右端点排序,方便解决区间取舍后对下一个区间的影响(如果不按右端点排序就有后效性了,不能用贪心解决)。
例题:P2255 [USACO14JAN] Recording the Moolympics S
同样,我们先按右端点排序,然后因为有两个节目可以同时录制,我们用 和 来代表两个节目的结束时间。
贪心策略:由于靠前的节目是结束时间更小的,所以结束后可以更快安排下一个节目,所以我们只需要按右端点排序后挨个判断节目是否可以即可。
例题:P11232 [CSP-S 2024] 超速检测
本题的前一部分求超速区间这里不再细讲了。
对于每一个区间 ,如果另一个区间 使得 ,也就是区间 被包含在了 里,那么显然满足了 就一定满足 ,且根据贪心策略,满足 是最优的。
所以我们按左端点排序,找到下标 满足 ,那么将 删除,最后剩下的区间是一定不会两两重叠的。
最后按普通的贪心(用 lower_bound 找离区间右端点最近的摄像头是最优的)即可完成。
注意精度误差带来的影响。
3 数据结构优化贪心——并查集
在有些时候,贪心的复杂度为 ,其中一个 的复杂度是寻找前面满足条件的元素所需的复杂度,所以我们可以用并查集优化。
例题:U213773 家庭作业
我们很容易推出贪心策略:先选得分大的,如果这个作业有时间就做,没时间直接舍去,但由于每次查找之前的时间都需要 ,总复杂度为 ,考虑并查集优化。
我们定义 为 天前的第一个空闲时间,那么查找这个作业是否可以就是 ,复杂度为 (路径压缩)。
例题:P1525 [NOIP 2010 提高组] 关押罪犯
很明显,我们需要让危害性较大的两个罪犯分到两个监狱里。我们用 表示第 个人和 个人放在一个监狱里, 表示跟 仇恨度最大的人是谁。
很明显,如果现在 已经有值了,所以为了他们并不互相冲突,只能将 和 放在一个监狱里面,如果没有 ,根据贪心策略,肯定将 和 放在两个监狱里。
4 数据结构优化贪心——优先队列
贪心中查找最大或最小值且两个元素在同一位置的查找范围一样,那么就可以用 的复杂度取代 的暴力枚举。
例题:[ABC407E] Most Valuable Parentheses
很明显,我们只要满足左括号的数量等于右括号的数量且在任何一个 的序列中的左括号都要大于右括号,所以我们只需要在前 个当中选择 个,可以证明保证从 到 会同时增加一个左括号和右括号。
所以我们可以用优先队列,从 枚举到 ,每次枚举到奇数位就将序列中最大的元素累加答案。
部分信息可能已经过时