此处的定义实际上是不明确的。我们所说的贪心算法,实际上是选择局部最优解的一个过程,而 D P \ DP DP也是选择局部最优解的一个过程。其中最大的区别在于: D P \ DP DP往往有一个较为严格的证明,而贪心往往没有。这里说的没有指其可能并不正确。
但是对于大多数的题目,我们的贪心的做法往往能够得到很多的分数。不难看到:即使贪心是不正确的,有时其正确的概率也会很高。
这里举出一个很好的例子:
[SCOI2008]城堡
我们可以想到的贪心:二分所使用的城堡数量,然后贪心地放置(周围没有就放,否则不放)。显然这是错误的。
7 0 3
0 0 0 0 1 2 3
1 1 1 1 1 1 1
这组数据已经可以卡掉贪心的算法。这道题的正确的方法包括模拟退火等等,但是并非简单的贪心。
这种的贪心不在我们的讨论范围内! 这里我们主要讨论有严格证明的贪心。
我将贪心的思考方法大致分为几大类。
Cow Acrobats
首先我们讨论只有两个的时候的情况。现在有两个牛 i \ i i和 j \ j j
i \ i i在上边的承受和 j \ j j在上边的承受 G \ G G为两者上方的承重和:
G + w i − s i , G + w i + w j − s j ; G + w j − s j , G + w i + w j − s i ; G + w_{i} - s_{i} \,\,\,,\,\,\, G + w_{i} + w_{j} - s_{j} \,\,\,;\\ G + w_{j} - s_{j} \,\,\,,\,\,\, G + w_{i} + w_{j} - s_{i} \,\,\,; G+wi−si,G+wi+wj−sj;G+wj−sj,G+wi+wj−si;
然后开始瞎讨论:
⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ \ \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots \cdots ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
然后得出结论 w i + s i \ w_{i}+s_{i} wi+si大的放下面。
color a tree
我们首先想到,一个节点被选择时,它儿子中权值最大的点必须放在其后面。这是显然的,现在我们要思考一下被绑过的和其他的点怎么排列 。
现在我们要求 A B \ AB AB和 X \ X X放在一起,现在观察 X A B \ XAB XAB和 A B X \ ABX ABX的值的比较:
A B X = W A ⋅ i + W B ⋅ ( i + 1 ) + W X ⋅ ( i + 2 ) X A B = W X ⋅ i + W A ⋅ ( i + 1 ) + W B ⋅ ( i + 2 ) ABX = W_{A} \cdot i + W_{B} \cdot (i+1) + W_{X} \cdot (i+2) \\ XAB = W_{X} \cdot i + W_{A} \cdot (i+1) + W_{B} \cdot (i+2) ABX=WA⋅i+WB⋅(i+1)+WX⋅(i+2)XAB=WX⋅i+WA⋅(i+1)+WB⋅(i+2)
我们可得到:
X A B − A B X = 2 W X − ( W A + W B ) XAB-ABX = 2 W_{X} - (W_{A} + W_{B}) XAB−ABX=2WX−(WA+WB)
这是将两个捆在一起的情况,我们由此可以大概推导出当将多个捆在一起的情况。
设将 A 1 , A 2 , A 3 ⋯ A k \ A_{1},A_{2},A_{3} \cdots A_{k} A1,A2,A3⋯Ak捆在一起
X A 1 A 2 ⋯ A k − A 1 A 2 ⋯ A k X = k W x − ∑ i = 1 k W A i XA_{1}A_{2} \cdots A_{k} - A_{1}A_{2} \cdots A_{k}X=kW_{x} - \sum_{i=1}^{k}W_{A_{i}} XA1A2⋯Ak−A1A2⋯AkX=kWx−i=1∑kWAi
这实际上是一个平均数,我们可以将平均数当做权值。
这样我们从叶子节点开始合并,每次合并选取最大的权值的合并并且改变权值。尽管原题目没有要求,大根堆可以优化这一过程。
这些都是基于对于两个东西的比较得出的结论。这是一个非常重要的经典方法。
有些时候我们可以对一个初始的决策进行调整,来达到最优解。
[JSOI2007]建筑抢修
首先我们想到直接按照 t 2 \ t2 t2排序然后一个一个修。这样是对的吗?不是。但是我们可以对这个决策进行调整。
排序之后从左到右轮流遍历整个序列。设当前总用时 t o t \ tot tot,如果 t o t + t 1 i ≤ t 2 i \ tot+t1_{i} \le t2_{i} tot+t1i≤t2i,就直接修即可,否则就找到已经修过的建筑中选择最大的 t 1 j \ t1_{j} t1j,如果 t j > t i \ t_{j}>t_{i} tj>ti就放弃打者。用反证法可以证明这个问题。
CF521D Shop
首先我们可以讨论对同一个 i \ i i的操作。必然是先赋值,再加再乘。
以上
这一部分没什么讲的,往往没有什么共同点。这里推荐几道题:CF140C New Year Snowmen等等
贪心的方法往往是千变万化的。如果大家希望证明,可以自行使用反证法,数学归纳等等。