< align=center><b> 贪婪算法</b></P> 虽然设计一个好的求解算法更像是一门艺术,而不像是技术,但仍然存在一些行之有效的能够用于解决许多问题的算法设计方法,你可以使用这些方法来设计算法,并观察这些算法是如何工作的。一般情况下,为了获得较好的性能,必须对算法进行细致的调整。但是在某些情况下,算法经过调整之后性能仍无法达到要求,这时就必须寻求另外的方法来求解该问题。, M! q2 P( g4 P) j* w
0 t7 u& w7 O4 p5 h* J+ b2 L+ y
本章首先引入最优化的概念,然后介绍一种直观的问题求解方法:贪婪算法。最后,应用该算法给出货箱装船问题、背包问题、拓扑排序问题、二分覆盖问题、最短路径问题、最小代价生成树等问题的求解方案。 / q# P) n7 p4 {: g3 S& t0 g$ Q ?( ]- x( e
6 N5 C& Q4 M# t) `0 v# C
) k a- `- u6 g" O5 G: i2 B
< align=center><EM> 最优化问题</EM></P> 2 D2 U1 B4 f3 S, @) C% M<>本章及后续章节中的许多例子都是最优化问题( optimization problem),每个最优化问题都包含一组限制条件( c o n s t r a i n t)和一个优化函数( optimization function),符合限制条件的问题求解方案称为可行解( feasible solution),使优化函数取得最佳值的可行解称为最优解(optimal solution)。# @; d) f6 r' p7 z4 ^$ V7 T, `
5 |) a: j: d" @- ?. s& ~( v
例1-1 [ 渴婴问题] 有一个非常渴的、聪明的小婴儿,她可能得到的东西包括一杯水、一桶牛奶、多罐不同种类的果汁、许多不同的装在瓶子或罐子中的苏打水,即婴儿可得到n 种不同的饮料。根据以前关于这n 种饮料的不同体验,此婴儿知道这其中某些饮料更合自己的胃口,因此,婴儿采取如下方法为每一种饮料赋予一个满意度值:饮用1盎司第i 种饮料,对它作出相对评价,将一个数值si 作为满意度赋予第i 种饮料。 ! \/ g9 [; u$ a' s0 Z* L/ U9 d ' J' H$ E; m" l* m5 q/ E 通常,这个婴儿都会尽量饮用具有最大满意度值的饮料来最大限度地满足她解渴的需要,但是不幸的是:具有最大满意度值的饮料有时并没有足够的量来满足此婴儿解渴的需要。设ai是第i 种饮料的总量(以盎司为单位),而此婴儿需要t 盎司的饮料来解渴,那么,需要饮用n种不同的饮料各多少量才能满足婴儿解渴的需求呢? S7 _( E- i+ Z! d9 N5 [# ^ # E) H9 B* y8 U3 Q$ i 设各种饮料的满意度已知。令xi 为婴儿将要饮用的第i 种饮料的量,则需要解决的问题是:7 O! | r \$ U' b2 K ?# c d6 R) o
; A( E, t# [: s+ p a! y! ~0 @2 V3 { 找到一组实数xi(1≤i≤n),使n ?i = 1si xi 最大,并满足:n ?i=1xi =t 及0≤xi≤ai 。' S: |5 P# Y" J6 ~$ E; t4 R
7 x3 N& I4 O. E8 a" r4 a! K
需要指出的是:如果n ?i = 1ai < t,则不可能找到问题的求解方案,因为即使喝光所有的饮料也不能使婴儿解渴。7 ?( d3 y; X$ U% M
$ v4 i- G' b/ ~' i" ?1 R6 U* m
对上述问题精确的数学描述明确地指出了程序必须完成的工作,根据这些数学公式,可以对输入/ 输出作如下形式的描述: & X! k4 p- ]8 D7 p8 b# M 0 i! |8 V6 U. }& N+ t% p 输入:n,t,si ,ai(其中1≤i≤n,n 为整数,t、si 、ai 为正实数)。, q6 ~( f, s8 d4 b/ t; Y0 c7 l/ h, J# a
6 x& P$ N# r6 d% X 输出:实数xi(1≤i≤n),使n ?i= 1si xi 最大且n ?i=1xi =t(0≤xi≤ai)。如果n ?i = 1ai <T,则输出适当的错误信息。 Y9 ~% s- H6 v4 M3 ]8 B
# i/ _- o/ f- b9 O$ r0 m! q5 C
在这个问题中,限制条件是n ?i= 1xi =t 且0≤xi≤ai,1≤i≤n。而优化函数是n ?i= 1si xi 。任何满足限制条件的一组实数xi 都是可行解,而使n ?i= 1si xi 最大的可行解是最优解。 9 I. R- S" ]; V* `: N, \3 e! ~, h; o- v' S+ o
例1-2 [装载问题] 有一艘大船准备用来装载货物。所有待装货物都装在货箱中且所有货箱的大小都一样,但货箱的重量都各不相同。设第i 个货箱的重量为wi(1≤i≤n),而货船的最大载重量为c,我们的目的是在货船上装入最多的货物。2 e r- s; k4 ~9 o
- d& ?6 ^3 Y* j$ F+ B0 f: E 这个问题可以作为最优化问题进行描述:设存在一组变量xi ,其可能取值为0或1。如xi 为0,则货箱i 将不被装上船;如xi 为1,则货箱i 将被装上船。我们的目的是找到一组xi ,使它满足限制条件n ?i = 1wi xi ≤c 且x i ? {0, 1}, 1 ≤i≤n。相应的优化函数是n ?i= 1xi 。 , c, f% ^/ U9 w) ]# J- N* K* I : h$ b& V2 E# {5 m2 A3 ^4 b e 满足限制条件的每一组xi 都是一个可行解,能使n ?i= 1xi 取得最大值的方案是最优解。* w- E% w) _2 [$ H
# Y' p$ r: N' d! e 例1-3 [最小代价通讯网络] 城市及城市之间所有可能的通信连接可被视作一个无向图,图的每条边都被赋予一个权值,权值表示建成由这条边所表示的通信连接所要付出的代价。包含图中所有顶点(城市)的连通子图都是一个可行解。设所有的权值都非负,则所有可能的可行解都可表示成无向图的一组生成树,而最优解是其中具有最小代价的生成树。 * z! |) p' r1 ~. Y0 P 0 s B" f& o0 k! g7 J) ` H$ n 在这个问题中,需要选择一个无向图中的边集合的子集,这个子集必须满足如下限制条件:所有的边构成一个生成树。而优化函数是子集中所有边的权值之和。</P>