到底怎么想到这道题用贪心的?

前言

笔者曾经痛苦地挣扎在oj的题海,对于贪心的题目,往往陷入一种“看题解恍然大悟,再做题DP回溯”的困境之中。但是现在,笔者发现了一个常见的贪心题目范式,分享给读者。

现有的一般贪心策略理论

贪心策略的思想一句话概括为局部最优等价于全局最优

为了使得这一等价成立,《算法导论》中给出了两条路径:

  • 最优子结构性质和贪心选择性质

  • 拟阵理论

    最优子结构:问题的最优解可以由若干个更小的子问题构造得到
    贪心选择性质:问题至少包含一个每次都“贪心选择”的最优解
    拟阵理论:在组合数学中,拟阵是一个对向量空间中线性独立概念的概括与归纳的数学结构。

虽然这给出了贪心策略的理论基石,但是证明一个问题的贪心选择性质和最优子结构性质并不简单,往往涉及到数学技巧和逻辑推理。这里以硬币选择问题举例:2023-12-23 硬币选择问题 硬币找零问题 poj3040 贪心选择性质 数学证明-CSDN博客

不仅如此,该书在16.5节中用拟阵理论化简的复杂问题,同样可以使用另一种绕开拟阵的贪心策略方法较为简明的解决,并得到正确的结果。

接下来的内容,不需要掌握上述任何一种理论,只基于笔者自定义“价值”理论展开。

价值:物体的某种有益的属性——这里的物体可以是具体的物体,也可以是抽象的区间和事件

“单价值”的贪心策略

在日常生活中,我们会不自觉地使用贪心算法。

比如,在7个物品中只能拿走3个物品,为了获取最大的价值,只需要拿走价值最高的三个即可。

值得一提,哈夫曼编码、Kruskal算法、Prim算法、Dijkstra算法也都是“单价值”贪心策略的,因为我们有且仅有一个衡量节点的指标。

“双价值”的贪心策略

oj中的贪心问题基本上都可以归约为“双价值”的贪心问题。

问题类型价值1价值2
区间问题具有左价值l,l越小越能覆盖左侧具有右价值r,r越大越能覆盖右侧
任务调度问题按时完成拥有奖励w(惩罚的情况自己理解)任务截止价值f,f越大就可以拖的越晚
(陶陶摘苹果体力w,体力花费越小越好摘大小b,越大苹果越好吃

区间问题中,又有五类常见的区间问题:

  • 区间合并问题
  • 选择不相交区间问题
  • 区间选点问题
  • 区间覆盖问题
  • 区间分组问题

详情请见一文读懂五类常见区间问题 - 知乎 (zhihu.com)

解决“双价值”问题的范式

“双价值问题”的解决范式一般有两种:

  1. 分数背包问题:将重量和价值两个价值重新归约为一个价值单位重量价值,再使用“单价值”的方法解决;
  2. 一般的双价值约束问题:将价值1排序,然后贪心地选择满足条件的价值2。

第二种范式这样做的理论依据是:这类问题价值1和2往往不能两全(否则根本不用做),而我们在满足条件情况下贪心大的价值2,排序保证我们选了大的价值1,而其他的选择要么在价值2上不满足条件,要么排序上小于选择的价值1,导致其不合法或非最优。

使用价值2排序亦然。有时两者算法复杂程度相同(例如区间问题),有时两者有一个更简单,但二者一定都是可以解决的。

区间分组问题(组内两两相交)

区间分组问题:将一组区间分为若干个区间集合,集合中的每一个区间两两相交;求最少集合数

显然,该问题中l越小,r越大越有价值,越可能被包含在某个集合中,越好被忽略。

如果选择价值一(l)从小到大排序(即价值高到价值低),那么在价值二(r)满足条件(被现有任何一个集合包含)时,就可以贪心地直接忽略这个区间的存在。

如果选择价值二(r)从大到小排序(即价值高到价值低),那么在价值一(l)满足条件(被现有任何一个集合包含)时,就可以贪心地忽视这个区间地存在。

值得注意的是,这道题实际上无论怎么排序事实上都能得到正确答案,原理大概为看待价值的角度可以是:l越大,r越小越有价值,越难以用一根针扎破,越容易排除更多的冗余区间。详情请见435. 无重叠区间 - 力扣(LeetCode)

区间覆盖问题

区间覆盖问题:使用一组区间覆盖给定区间,求最少区间数

显然,该问题中l越小,r越大越有价值,越能覆盖更大的范围。

如果选择价值一(l)从小到大排序(即价值高到价值低),那么在价值二(r)满足条件(不能使给定区间出现空缺)时,就可以贪心地选择r最大的那个。

如果选择价值二(r)从大到小排序(即价值高到价值低),那么在价值一(l)满足条件(不能使给定区间出现空缺)时,就可以贪心地选择l最小的那个。

区间合并问题/区间分组问题(组间互不相交)

区间合并问题:将一组区间分为若干个区间集合,不同集合的区间无任何交集;求最小区间数

显然,该问题中l越小,r越大越有价值,越能让所有区间都被它囊括其中。

如果选择价值一(l)从小到大排序(即价值高到价值低),那么在价值二(r)满足条件(被现有任何一个集合包含)时,就可以贪心地直接忽略这个区间的存在。

如果选择价值二(r)从大到小排序(即价值高到价值低),那么在价值一(l)满足条件(被现有任何一个集合包含)时,就可以贪心地忽视这个区间地存在。

任务调度问题

任务调度问题:完成一组耗时1的任务,在fi内完不成有惩罚wi,惩罚最小

转化为赚钱wi,赚钱最多即可。

该问题中w越大,f越晚越好,因为又能拖着完成,又能有钱赚。

如果选择价值一(w)从大到小排序(即价值高到价值低),那么在价值二(f)满足条件(这之前还有空位)时,就可以贪心地把钱挣了。

如果选择价值二(f)从大到小排序(即价值高到价值低),那么在价值一(w)满足条件(这个f中没有价值更高的)时,就可以贪心地把钱挣了。

总结

本文详细解读的“双价值”问题,是一类看似复杂,要用dp解决,而实际上特别简单,只需要脑测一下价值排序,再简单分析一下题意就能解决的问题。

特别注意的是,范式能解决的双价值问题必须这样的描述:

  • 选择若干物品,使得总价值最大,重量最小;(对)
  • 背包限制为W,选择若干物品,使得总价值最大;(错,变质了)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值