1 前言
对于一些NP-Hard问题,我们无法找到一个精确的求解方法。使用贪心思想采取贪心算法来求取近似解就成了常用的选择。很多算法名著对贪心算法都有很明确的讲解,这里对贪心算法摘取一下重点,然后我们要引出贪心算法背后的理论依据——拟阵理论。对于拟阵理论,可以查找一些入门典籍,如刘桂真,陈庆华著《拟阵》。
2 贪心算法
也称作贪婪算法(Greedy Algorithm),通过做一系列的选择来给出某一问题的最优解。对算法中的每一个决策点做一个在当时看起来是最佳的选择。这是贪心算法的核心思想。但是这种启发式策略不是总能产生出最优解,但常常能给出最优解。贪心算法以动态规划作为基础,大致遵循着这样的步骤:
1.确定待解决问题的最优子结构;
2.设计递归求解方式;
3.证明在递归的任一阶段,最优选择之一总是贪心的。那么做贪心选择是合适的;
4.证明通过做贪心选择,所有的子问题都为空(除一个以外).
5.设计实现贪心策略的递归算法;
6.将设计好的递归算法转换成迭代算法。
2.1 贪心选择性
一个全局最优解可以通过局部最优(贪心)选择来达到。换言之,当考虑做何种选择时,我们只考虑对当前问题的选择而不考虑子问题的结果。贪心算法不同于动态规划之处就在于此,在动态规划中,每一步都要做出选择,但是这些选择依赖于子问题的解,解动态规划问题一般是自底向上,从小问题处理到大问题。而贪心算法中,我们所做的总是当前看似最佳的选择,然后在解决经过贪心选择之后所出现的子问题。其作出的当前的选择可能要依赖于已经做出的所有选择,但不依赖于未做出的选择或子问题的解。贪心算法采取的贪婪策略往往是自顶向下的。核心所在就是要证明每一步所做的贪心选择最终能产生一个全局最优解。
2.2 最优子结构
对于一个问题,如果它的一个最优解包含了其子问题的最优解,则称该问题具有最优子结构。
2.3 设计贪心算法的一般步骤
1.将优化问题转化为:先做出选择,再解决剩下的一个子问题;
2.证明原问题总是有一个最优解是做贪心选择而得到的,从而证明贪心选择的安全性;
3.说明做出贪心选择之后,剩余的子问题具有一个性质:如果将子问题的最优解和所做的贪心选择联合,可以得到原问题的一个最优解。
3 拟阵
首先请明确:拟阵理论不能完全覆盖所有的贪心算法(如赫夫曼编码问题),但它可以覆盖大多数具有实际意义的情况。首先介绍拟阵的概念。(有些文献也称作矩阵胚)
3.1 定义 拟阵
拟阵(Matroid)是满足如下条件的一个序对M = ( S , l ) M=(S,l)M=(S,l):
1.S SS是一个非空有穷集合;
2.l ⊆ 2 S l \subseteq 2^Sl⊆2S且ϕ ∈ l \phi \in lϕ∈l
3.l ll满足交换性质(Augmentation):若A ∈ l , B ∈ l A \in l, B \in lA∈l,B∈l且∣ A ∣ < ∣ B ∣ \left | A \right | < \left | B \right |∣A∣<∣B∣,则∃ x ∈ B − A s . t . A ∪ { x } ∈ l \exists x \in B-A s.t. A \cup \left \{ x\right \} \in l∃x∈B−As.t.A∪{x}∈l
4.l ll满足遗传性质(Downward closure):若B ∈ l , A ⊆ B B\in l, A \subseteq BB∈l,A⊆B,则A ∈ l A \in lA∈l.称B BB是S SS的独立子集,这样B BB的任意子集也都是S SS的独立子集。
3.2 拟阵的实例
G = ( V , E ) G=(V,E)G=(V,E)是一个无向图,则M G = ( S G , l G ) M_G=(S_G,l_G)MG=(SG,lG)是一个拟阵.这里M G M_GMG的定义如下:
集合S G S_GSG定义为E EE,即G GG的边集;
若A AA是E EE的子集,则A ∈ l G A\in l_GA∈lG当且仅当A AA是无回路的。即,一组边A AA是独立的当且仅当子图G A = ( V , A ) G_A=(V,A)GA=(V,A)构成了一个森林。
证明:
1)显然S G = E S_G=ESG=E是一个有穷集合。
2)l G l_GlG是遗传的。对于任意的B ∈ I G , A ⊂ B B \in I_G,A \subset BB∈IG,A⊂B,都有边集A ∈ l G A\in l_GA∈lG,原因是从无环的一组边中去掉一些边并不会产生出回路。
3)具有k kk条边的森林恰好包含∣ V ∣ − k |V|-k∣V∣−k棵树。若G A = ( V , A ) G_A=(V,A)GA=(V,A)和G B = ( V , B ) G_B=(V,B)GB=(V,B)是G GG的森林,且∣ B ∣ > ∣ A ∣ |B|>|A|∣B∣>∣A∣,则G A G_AGA中有∣ V ∣ − ∣ A ∣ |V|-|A|∣V∣−∣A∣棵树,G B G_BGB中有∣ V ∣ − ∣ B ∣ |V|-|B|∣V∣−∣B∣棵树。由于G B G_BGB中的树比G A G_AGA中的树要少,必有边e ( u , v ) ∈ G B − G A e(u,v)\in G_B-G_Ae(u,v)∈GB−GA而且连接G A G_AGA中的两棵树。将e ee添加进A AA,不会产生回路。A ∪ { e } ∈ l A\cup \left \{e \right \} \in lA∪{e}∈l。
得证。
3.3 极大独立子集
首先明确可扩展元素的概念
3.3.1 定义 可扩展元素
给定拟阵M = ( S , l ) M=(S,l)M=(S,l),对于l ll中的独立子集A ∈ l A \in lA∈l,若∃ x ∉ A , s . t . \exists x \notin A, s.t.∃x∈/A,s.t.将x xx加入A AA中仍然保持独立性,即A ∪ { x } ∈ l A \cup \left \{ x \right \} \in lA∪{x}∈l,则称x xx为A AA的可扩展元素。当拟阵M MM中独立子集A AA没有可扩展元素时,即A AA不被M MM中别的独立子集所包含时。称A AA为极大独立子集。所有的极大独立子集都具有相同的势。
3.3.2 定义 带权拟阵
若对给定拟阵M = ( S , l ) M=(S,l)M=(S,l)中S SS指定权函数w ( ⋅ ) , s . t . ∀ x ∈ S , w ( x ) > 0 w(\cdot),s.t. \forall x \in S, w(x)>0w(⋅),s.t.∀x∈S,w(x)>0,则称拟阵M MM为带权拟阵。那么按此权函数,对于S SS的子集A AA有w ( A ) = ∑ x ∈ A w ( x ) w(A)=\sum_{x\in A}w(x)w(A)=∑x∈Aw(x).
适宜用贪心方法获得最优解的许多问题,都可以归结为在加权拟阵中找出一个具有最大权值的独立子集问题。因为任意元素的权值都是正的,故找出的最优子集同时也是最大子集。
下面是求带权拟阵最优子集的贪心算法。
3.4 求带权拟阵最优子集的贪心算法
G r e e d y ( M , w ) { A ← ϕ ; s o r t M S i n t o m o n o t o n i c a l l y d e c r e a s i n g o r d e r b y w e i g h t w ; while ( M S ≠ ϕ ) { x ← g e t M a x ( M S ) ; if ( A ∪ { x } ∈ M l ) A ← A ∪ { x } ; } return A ; } \begin{equation} \begin{aligned} &Greedy(M,w) \; \{ \\ &\;\;\;\;A \leftarrow \phi ; \\ &\;\;\;\;sort\,M_S\,into\,monotonically\,decreasing\,order\,by\,weight\,w; \\ &\;\;\;\;\textbf{while}\;(M_S \neq \phi)\; \{ \\ &\;\;\;\;\;\;\;\;x\leftarrow getMax(M_S);\\ &\;\;\;\;\;\;\;\;\textbf{if} \;(A \cup \left \{ x \right \} \in M_l)\\ &\;\;\;\;\;\;\;\;\;\;\;\;A\leftarrow A \cup \left \{ x \right \};\\ &\;\;\;\; \} \\ &\;\;\;\;\textbf{return}\;A;\\ &\} \end{aligned} \end{equation}Greedy(M,w){A←ϕ;sortMSintomonotonicallydecreasingorderbyweightw;while(MS=ϕ){x←getMax(MS);if(A∪{x}∈Ml)A←A∪{x};}returnA;}
该算法排序时间复杂度为O ( N l o g N ) O(NlogN)O(NlogN),共判断N NN次,设判断复杂度为f ( N ) f(N)f(N),则整个算法运行时间为O ( N l o g N + N f ( N ) ) O(NlogN+Nf(N))O(NlogN+Nf(N))
现证明算法返回的结果是一个最优子集。
3.4.1 引理1(拟阵具有贪心选择性质)
假设M = ( S , l ) M=(S,l)M=(S,l)是一个具有权函数w ( ⋅ ) w(\cdot)w(⋅)的加权拟阵,且S SS被按权值的单调减顺序排列。设x xx是S SS的第一个使{ x } \left \{x\right \}{x}独立的元素。如果x xx存在,则存在S SS的一个包含x xx的最优子集A AA.
3.4.2 引理2
设M = ( S , l ) M=(S,l)M=(S,l)为任意一个拟阵。如果x xx是S SS的任意元素,是S SS的独立子集A AA的一个可扩展元素,那么x xx也必然是ϕ \phiϕ的一个可扩展元素。
推论 设M = ( S , l ) M=(S,l)M=(S,l)为任意一个拟阵。如果集合S SS中的元素x xx不是空集的可扩展元素,那么x xx也不会是S SS的任意独立子集A AA的一个可扩展元素。(这个推论说明了任何元素如果不能立即被选择,则以后也决不会被选择。所以,在开始时,对S SS中的非空集合的可扩展元素不予选择不会漏掉解,因为它们以后也不会被选择。)
3.4.3 引理3(拟阵具有最优子结构性质)
设x xx为S SS中被作用于加权拟阵M = ( S , l ) M=(S,l)M=(S,l)的G r e e d y GreedyGreedy算法第一个选择的元素。找一个包含x xx的具有最大权值的独立子集问题,可以化归为找出加权矩阵M ′ = ( S ′ , l ′ ) M'=(S',l')M′=(S′,l′)的一个具有最大权值的独立子集问题,此处
S ′ = { y ∈ S ∣ { x , y } ∈ l } S'=\left \{y\in S|\left \{x,y \right \}\in l\right \}S′={y∈S∣{x,y}∈l}
l ′ = { B ⊂ S − { x } ∣ B ∪ { x } ∈ l } l'=\left \{B\subset S-\left \{x\right \}|B\cup \left \{x\right \}\in l\right \}l′={B⊂S−{x}∣B∪{x}∈l}
其中,M ′ M'M′权函数为受限于S ′ S'S′的M MM的权函数(即M MM的由x xx引起的收缩)。
故可得定理,G r e e d y GreedyGreedy算法返回最优子集。
这样可得到一个定理 拟阵上贪心算法的正确性
3.5 定理 拟阵上贪心算法的正确性
如果给定M = ( S , l ) M=(S,l)M=(S,l)为一个具有权函数w ( ⋅ ) w(\cdot)w(⋅)的加权拟阵,则调用G r e e d y ( M , w ) Greedy(M,w)Greedy(M,w)返回一个最优子集.
4 后记
拟阵提供给绝大部分贪心算法很好的理论背景,(但不能把所有的贪心算法都覆盖全面),在我们使用贪心算法解决问题时,应该考察其是否满足拟阵的相应约束,可否用拟阵理论的背景给予一些证明.应用拟阵的题目虽然不常见,但却是某些贪心问题强力解法。其独立扩充公理往往成为证明模型符合拟阵条件的关键。
本文只介绍了拟阵的基本概念以及拟阵和贪心算法的关系,若继续深入研究,可以参阅刘桂真,陈庆华编著的《拟阵》一书。
5 参考文献
[1] Thomas H.Cormen Charles E.Leiserson Ronald L.Rivest Clifford, Stein introduction to algorithms
[2] 刘桂真,陈庆华,拟阵,国防科技大学出版社,1994