来自:Va义 > 馆藏分类
配色: 字号:
编程-贪心算法
2014-11-13 | 阅:  转:  |  分享 
  
安徽芜湖一中江涛

1

贪心算法概论



贪心算法一般来说是解决“最优问题”,具有编程简单、运行效率高、空间

复杂度低等特点。是信息学竞赛中的一个有为武器,受到广大同学们的青睐。本

讲就贪心算法的特点作些概念上的总结。

一、贪心算法与简单枚举和动态规划的运行方式比较

贪心算法一般是求“最优解”这类问题的。最优解问题可描述为:有n个输入,

它的解是由这n个输入的某个子集组成,并且这个子集必须满足事先给定的条

件。这个条件称为约束条件。而把满足约束条件的子集称为该问题的可行解。这

些可行解可能有多个。为了衡量可行解的优劣,事先给了一个关于可行解的函数,

称为目标函数。目标函数最大(或最小)的可行解,称为最优解。



a)求“最优解”最原始的方法为搜索枚举方案法(一般为回溯法)。



除了极简单的问题,一般用深度优先搜索或宽度优先搜索。通常优化方法为利

用约束条件进行可行性判断剪枝;或利用目标函数下界(或上界),根据当前最

优解进行分枝定界。



b)其次现今竞赛中用的比较普遍的动态规划(需要满足阶段无后效性原则)。



动态规划主要是利用最最优子问题的确定性,从后向前(即从小规模向大规模)

得到当前最优策略,从而避免了重复的搜索。



举例说明:求多段图的最短路径。



在图(1)中,我们省略了各线段的长度。



1

2

3

4

5

6

7

8

9

10

11

图(1)

安徽芜湖一中江涛

2

如果用回溯法,搜索树大致如下:



显然,上面的搜索有大量重复性工作。比如节点8、9、10到11的最短路分别

被调用了9次,从节点5、6、7到节点11也分别搜索了3次。



如果先算出节点8、9、10到11的最短路,由于它与前面的点无关,因此最优

值确定下来,再用它们求定节点5、6、7到节点11的最短路径。同理,再用节

点5、6、7的最优值,来求节点2、3、4优值。最后从节点2、3、4推出1到

11的最优值。显然复杂度大为降低。



当然,如果本题把简单搜索改为搜索+记忆化的方法,则就是得能动态规划的

原理,本质上就是动态规划,只是实现的方法不同与传统的表格操作法。搜索+

记忆化算法有其特有的特点,以后再讨论。





c)贪心算法则不同,它不是建立在枚举方案的基础上的。它从前向后,根据当

前情况,“贪心地”决定出下一步,从而一步一步直接走下去,最终得到解。



假如上面的例子中,我们定下这样的贪心策略:节点号k%3==1。则有图3:







1

234

567567567

A89A89A89A89……………………………..

图(2)

11

安徽芜湖一中江涛

3

显然,它只访问了节点1、4、7、10、11,工作量最少,效率最高。当然,对

本题来说,它不能得到最优解―――最短路径。



从图3中可以看出,贪心算法是一种比动态规划更高效的算法。只是要保证得

到最优解是贪心算法的关键。



贪心算法的一般框架为:



ProcedureGreedy(A,n)//A问题有n个输入

Begin

Init(ans)//初始化

fori:=1tondo

now=select(A)//按设计的标准选取一个“节点”

delete(A,now)//把A中的now删掉

ifcan(ans,now)thenunio(ans,now)//如果可行性通过,放入解中。

endfor

end;













1

234

567567567

A89A89A89A89……………………………..

图(3)

11

安徽芜湖一中江涛

4

二、贪心算法的关键――――正确性证明

动态规划要满足最优子结构原则,贪心算法呢?就目前的资料看,有个证明

模型是“矩阵胚理论”,但要证明一个问题是矩阵胚,十分困难。并且也不常见

的可用贪心算法问题都能用矩阵胚来证明。因此,可以认为贪心算法的正确性证

明是个难点。因此有些选手在没能证明时,也大胆设想结论应该是正确的。有时

这难免会放错。

例如95年NOI中的“石子合并”一题:

例一、石子合并

试题:

在一个圆形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并

成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,

记为该次合并的得分。

编一程序,由文件读入堆数N及每堆石子数(≤20)

选择一种合并石子的方案,使得做N-1次合并,得分的总

和最小;选择一种合并石子的方案,使得做N-1次合并,

得分的总和最大。

例如,图4所示的4堆石,每堆石子数(从最上面的

一堆数起,顺时针数)依次为4594。则3次合并得分总和

最小的方案为图5,得分总和最大的方案为图6。













图4

4

9

45

















总得分=8+13+22=43

图5



4

9

45

8

9

5

9

13

22

















总得分=14+18+22=54

图6

4

9

45

4

4

1418

4

22

安徽芜湖一中江涛

5

输入数据

文件名由键盘输入,该文件内容为:

第1行为石子堆数N;

第2行为每堆石子数,每两个数之间用一个空格符分隔。

输出数据

输出文件名为output.txt;

从第1至第N行为得分最小的合并方案。第N+1行是空行。从第N+2行

到第2N+1行是得分最大合并方案。

每种合并方案用N行表示,其中第i行(1≤i≤N)表示第i次合并前各堆石

子数(依顺时针次序输出,哪一堆先输出均可)。要求将待合并的两堆石子数以相

应的负数表示,以便标识。



输入输出示例:







当时这题是第一次出现,几乎有半数以上人都选择了贪心算法―――每次选

相邻和最小的两堆石子合并。

其实由于只能是相邻的两堆石子合并,并不能套用经典的哈夫曼树算法。本

题给的样例数据实际上是一个“陷阱”,造成了用贪心法即可解决的假象。

当一个贪心算法不能确定其正确性时,在使用之前,应该努力去证明它的不

正确性。而要证明不正确性,一种最简单的形式就是举一个反例。本例的反例见

图7。



INPUT.TXTOUTPUT.TXT

4-459-4

4594-8-59

-13-9

22

4-5-94

4-14-4

-4-18

22

















图7

5

2

4

43

6

贪心算法的最小值为:

(2+3)=5

(4+5)=9

(4+5)=9

(9+6)=15

(15+9)=24

5+9+9+15+24=62

另一种方法的最小值为:

(2+4)=6

(3+4)=7

(5+6)=11

(7+6)=13

(11+13)=24

6+7+11+13+24=61

安徽芜湖一中江涛

6

常见的证明方法:

贪心算法的正确性证明虽然不容易,但一些常见的方法还是值得总结的。



a)构造法

根据描述的算法,用贪心的策略,依次构造出一个解,可证明一定是

合法的解。即用贪心法找可行解。



b)反证法

用贪心的策略,依次构造出一个解S1。假设最优解S2不同与S1,可

以证明是矛盾的。从而S1就是最优解。



c)调整法

用贪心的策略,依次构造出一个解S1。假设最优解S2不同与S1,找

出不同之处,在不破坏最优性的前提下,逐步调整S2,最终使其变为S1。

从而S1也是最优解。



下面分别举例说明。

例2士兵排队问题(1996年中国队选拔赛)----构造法证明

试题:

有N个士兵(1≤N≤26),编号依次为A,B,C,...。队列训练时,指挥官

要把一些士兵从高到矮依次排成一行,但现在指挥官不能直接获得每个人的身高

信息,只能获得“P1比P2高”这样的比较结果(P1,P2∈A,B,C,...,Z,记

为P1>P2),如“A>B”表示A比B高。

请编一程序,根据所得到的比较结果求出一种符合条件的排队方案。

注:比较结果中没有涉及到的士兵不参加排队



输入数据

比较结果从文本文件中读入(文件名由键盘输入),每个比较结果在文本文

件中占一行。



输出要求

若输入数据无解,打印“NoAnswer!”信息,否则从高到矮依次输出每一

个士兵的编号,中间无分隔符,并把结果写入文本文件中,文件名由键盘输入。



输入输出示例

INPUT.TXT

A>B

B>D

F>D



OUTPUT.TXT

AFBD



安徽芜湖一中江涛

7

显然用每次选“偏序中最高士兵”的贪心算法就可构造出一个可行解。这个

问题转就是“拓扑排序”问题。可这样证明:如果有解,就一定无环,因此每步

贪心都一定能进行下去。

经典的“找欧拉回路”问题也类似。



例3排队问题----反证法证明

试题:

在一个超市,有N个人排队到一个柜台付款,已知每个人需要处理的时间为

Ti(0
输入数据

文本文件中第一行为一个正整数N≤10000,第二行有N个不超过1000的正

整数Ti。

输出要求

只一个正整数:大家排队时间的最小总和。

输入输出示例

本题的贪心算法为:N个数据从小到大排序,就是这N个人的最佳排序方案。

求部分和的和即可得到答案。



反证法证明如下:

假设有最优解序列S1,S2,S3….,Sn,如果S1不是最小的Tmin,不妨设

Sk=Tmin,将S1与Sk对调。显然对Sk之后的人没影响,对Sk之前的人等待时

间都减少了(S1-Sk)>0。从而新的序列比原最优解序列好,矛盾!

固S1为最小时间。

同理可证S2是第二小的数,……。

证毕。



下面的调整法也有类似的思想,只是侧重点在“这样调整不会差”。



例4切巧克力问题----调整法证明

试题

我们提供给你一块mn的巧克力(如图8所示),你需要将这块巧克力切割成11的单

位巧克力。

INPUT.TXT

4

51087



OUTPUT.TXT

67

安徽芜湖一中江涛

8



图8巧克力



具体来说,对于一块巧克力,你有两种切割的方法。一种是沿着某条竖线将巧克力切成

两块,另外一种自然是沿着某条横线将巧克力切成两块。切割需要一定的花费,费用的计算

与所切割的巧克力的大小没有关系,而只于沿着哪条线切割有关。我们将沿着横线切割的费

用定义为y1、y2、……、ym-1;同样的,将沿着竖线切割的费用定义为x1、x2、……、xn-1。

现在,需要你计算的就是,怎样切才能使总费用最少?

在图8中,如果我们先沿着横线将整块巧克力切成四块,然后对于每一小块,分别沿着

竖线切割,那么总共的费用就是4)(4321321′++++++xxxxyyy。

【输入格式】

输入文件chocolate.in的第一行包含两个整数)1000,1(,££mnmn,表示巧克力的大

小。接下来的n-1行每行包含一个整数,分别表示沿竖线切割的费用(上图中x1,x2,……),

接下来的m-1行也是每行包含一个整数,表示沿横线切割的费用(上图中的y1,y2,……)

【输出格式】

输出文件chocolate.out应该包含一个整数,表示你得到的最小切割费用。



















样例输入

64

2

1

3

1

4

4

1

2



样例输出

42

安徽芜湖一中江涛

9

分析:

不妨设,Xi已经从大到小排序;Yi也同样。

如果把问题简化,只有横的切Xi或只有竖的切Yi,则显然和排队问题是一样

的,可以用贪心算法。横、竖可以交错切呢?

对任意一种方案,只看其中横切的Xi序列,如果不是从大到小排列,找到第

一个违反有序原则的,设为Xp,找出应该在这个位置的――即后面不小于Xp

的Xq,把Xp与Xq对调,显然新方案会更好。如此,有



结论一:

任意最优方案在不改变竖切次序前提下,可调整成横切是有序的最优解。



同理,有



结论二:

任意最优方案在不改变横切次序前提下,可调整成竖切是有序的最优解。



综合结论一和结论二,有



结论三:

任意一种最优方案,可调整成横切、竖切都有序的最优解。



如此,可简单得到动态规划算法,时空复杂度约为O(106)。



上面虽然用了贪心算法的反证法解决了问题,但没有将贪心算法思想进行到

底。我们可以进一步用调整法和反证法的思想,将最优解调整到不分横切、竖切,

都是递减的。



简单证明如下:



设有最优方案序列XY[1..n+m],序列中任意两相邻项XY[i]和XY[i+1],记为

a和b,若a≤b,分三种情况考虑:

(1)若a、b同是横切,显然交换a、b不影响最优解;

(2)若a、b同是竖切,显然交换a、b也不影响最优解;

(3)a和b不同,最交换a、b后,增加费用a,减少费用为b,共增加费用为

(a-b)≤0,不会破坏最优性。



反复检查,最终调整为全部有序的最优解。



这样最终得到一个简单的算法:只要排序就可以了。



进一步,如果切过的巧克力可分别拿开,各自选方案切割。也可用调整法证明

上面的方案也是最优解。





安徽芜湖一中江涛

10

流水线调度问题



由于篇幅关系,后面的两节就简单列个提纲。



三、一些经典贪心算法问题



磁带最优存储



背包问题



有限期的作业排序



哈夫曼树



最小生成树---Prim算法



最小生成树---Kruskla算法



教室问题



四、贪心算法应用的多样性

(1)构造出次序

在众多的选择中,按预先设计的某种次序来确定当前要找的下一步选择。



单源最短路径:Dijkstra算法

最小生成树



(2)局部(阶段)正确

有时整个问题不能用贪心法,但我们确定了部分因素后,后面的方案就可以

用贪心算法了。即通常简称:枚举+贪心



从汽车过沙漠到登山问题



(3)快速求得一“较好”可行解

前面提到的搜索枚举方案法中,要很多题都可通过贪心算法得到一个“较

优可行解”。有时甚至用“启发+随机化”多次贪心,能得到一个很好的上界(或

下界)。



(4)快速分枝定界

安徽芜湖一中江涛

11

接上面话题,在搜索过程中,有时也可以用贪心算法预测已有方案以后可能

达到的最小值(或最大值),再用“当前最好解”进行分枝定界。



从原始背包问题到0/1背包



(5)对称性游戏

根据问题的特点,直接确定一步,保证次把必败状态留给对方。



圆桌放硬币游戏

取数游戏





献花(0)
+1
(本文系Va义首藏)