贪心法专题.docx

上传人:b****3 文档编号:2963922 上传时间:2022-11-16 格式:DOCX 页数:12 大小:153.63KB
下载 相关 举报
贪心法专题.docx_第1页
第1页 / 共12页
贪心法专题.docx_第2页
第2页 / 共12页
贪心法专题.docx_第3页
第3页 / 共12页
贪心法专题.docx_第4页
第4页 / 共12页
贪心法专题.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

贪心法专题.docx

《贪心法专题.docx》由会员分享,可在线阅读,更多相关《贪心法专题.docx(12页珍藏版)》请在冰豆网上搜索。

贪心法专题.docx

贪心法专题

算法设计技术——贪心法专题

一、贪心法的设计思想

正如其名字一样,贪心法(greedymethod)在解决问题的策略上目光短浅,只根据当前已有的信息做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。

考虑用贪心法求解付款问题(paymentproblem)。

假设有面值为5元、2元、1元、5角、2角、1角的货币,需要找给顾客4元6角现金,为使付出的货币的数量最少,首先选出1张面值不超过4元6角的最大面值的货币,即2元,再选出1张面值不超过2元6角的最大面值的货币,即2元,再选出1张面值不超过6角的最大面值的货币,即5角,再选出1张面值不超过1角的最大面值的货币,即1角,总共付出4张货币。

在付款问题每一步的贪心选择中,在不超过应付款金额的条件下,只选择面值最大的货币,而不去考虑在后面看来这种选择是否合理,而且它还不会改变决定:

一旦选出了一张货币,就永远选定。

付款问题的贪心选择策略是尽可能使付出的货币最快地满足支付要求,其目的是使付出的货币张数最慢地增加,这正体现了贪心法的设计思想。

上述付款问题应用贪心法得到的是整体最优解,但是如果把面值改为3元、1元、8角、5角、1角,需要找给顾客4元6角现金,则找给顾客的是1个3元、1个1元、1个5角和1个1角共4张货币,但最优解却是3张货币:

1个3元和2个8角。

由于贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优,这种局部最优选择并不总能获得整体最优解(optimalsolution),但通常能获得近似最优解(near-optimalsolution)。

如果一个问题的最优解只能用蛮力法穷举得到,则贪心法不失为寻找问题近似最优解的一个较好办法。

例1埃及分数

【问题】埃及同中国一样,也是世界文明古国之一。

古埃及人只用分子为1的分数,在表示一个真分数时,将其分解为若干个埃及分数之和,例如:

7/8表示为1/2+1/3+1/24。

埃及分数问题(Egyptfraction)要求把一个真分数表示为最少的埃及分数之和的形式。

【想法】一个真分数的埃及分数表示不是唯一的,例如:

7/8又可以表示为1/8+1/8+1/8+1/8+1/8+1/8+1/8。

显然,把一个真分数表示为最少的埃及分数之和的形式,其贪心策略是选择真分数包含的最大埃及分数,以7/8为例,7/8>1/2,则1/2是第一次贪心选择的结果;7/8–1/2=3/8>1/3,则1/3是第二次贪心选择的结果;7/8–1/2–1/3=1/24,则1/24是第三次贪心选择的结果,即7/8=1/2+1/3+1/24。

接下来的问题是:

如何找到真分数包含的最大埃及分数?

设真分数为A/B,B除以A的整数部分为C,余数为D,则有下式成立:

B=A×C+D

即:

B/A=C+D/A

则:

A/B>1/(C+1)

即1/(C+1)即为真分数A/B包含的最大埃及分数。

设E=C+1,由于

A/B–1/E=((A×E)–B)/(B×E)

则真分数减去最大埃及分数后,得到真分数((A×E)–B)/B×E,该真分数可能存在公因子,需要化简,可以将分子和分母同时除以最大公约数。

【算法】设函数EgyptFraction实现埃及分数问题,算法用伪代码描述如下:

算法7.1:

埃及分数EgyptFraction

输入:

真分数的分子A和分母B

输出:

最少的埃及分数之和

1.E=B/A+1;

2.输出1/E;

3.A=A*E–B;B=B*E;

4.求A和B的最大公约数R,如果R不为1,则将A和B同时除以R;

5.如果A等于1,则输出1/B,算法结束;否则转步骤1重复执行;

 

例2TSP问题

【问题】TSP问题是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。

【想法1】TSP问题的贪心策略可以采用最近邻点策略:

从任意城市出发,每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。

如图7.1(a)所示是一个无向图的代价矩阵,从顶点1出发,按照最近邻点的贪心策略,得到的路径是1→4→3→5→2→1,总代价是14,求解过程如图7.1(b)~(f)所示。

 

需要说明的是,用最近邻点贪心策略求解TSP问题所得的结果不一定是最优解,例如,图7.1(a)中从顶点1出发的最优解是1→2→5→4→3→1,总代价只有13。

当图中顶点个数较多并且各边的代价分布比较均匀时,最近邻点策略可以给出较好的近似解,不过,这个近似解以何种程度近似于最优解,却难以保证。

例如,在图7.1中,如果增大边(2,1)的代价,则总代价只好随之增加,没有选择的余地。

【算法1】设图G中n个顶点的编号为{1,2,…,n},cij表示顶点i到顶点j的代价(1≤i,j≤n),集合V存储图的顶点,集合P存储经过的边,从顶点w出发采用最近邻点策略求解TSP问题的算法如下:

算法7.2:

最近邻点策略求解TSP问题

输入:

无向带权图G=(V,E)

输出:

回路长度TSPLength

1.初始化:

P={};TSPLength=0;

2.u=w;V=V-{w};

3.循环直到集合P中包含n-1条边

3.1查找与顶点u邻接的最小代价边(u,v)并且v属于集合V;

3.2P=P+{(u,v)};V=V-{v};TSPLength=TSPLength+cuv;

3.3输出经过的路径uv,u=v,转步骤3继续求解;

4.输出TSPLength+cuw;

 

例3图着色问题

【问题】给定无向连通图G=(V,E),图着色问题(graphcoloringproblem)求图G的最小色数k,使得用k种颜色对G中的顶点着色,可使任意两个相邻顶点着不同颜色。

例如,图7.3所示的无向图可以只用两种颜色着色,将顶点1、3和4着一种颜色,将顶点2和顶点5着另外一种颜色。

 

【想法】假定k个颜色的集合为{1,2,…,k}。

一种显然的贪心策略是选择一种颜色,用该颜色为尽可能多的顶点着色,具体地,选取颜色1,依次考察图中的未被着色的每个顶点,如果某顶点可以用颜色1着色,换言之,该顶点的邻接点都还未被着色,则用颜色1为该顶点着色;再选择颜色2,依次考察图中的未被着色的每个顶点,如果某顶点着颜色2与其相邻顶点的着色不发生冲突,则用颜色2为该顶点着色;如果还有未着色的顶点,则选取颜色3并为尽可能多的顶点着色,依此类推。

需要说明的是,贪心法求解图着色问题得到的不一定是最优解。

考虑一个具有2n个顶点的无向图,顶点的编号从1到2n,当i是奇数时,顶点i与除了顶点i+1之外的其他所有编号为偶数的顶点邻接,当i是偶数时,顶点i与除了顶点i-1之外的其他所有编号为奇数的顶点邻接,这样的图称为二部图(bipartitegraph)。

在二部图中,顶点可以分成两个集合V1(编号为奇数的顶点集合)和V2(编号为偶数的顶点集合),并且每一条边都连接V1中的一个顶点和V2中的一个顶点。

图7.4所示就是一个具有8个顶点的二部图。

 

显然,二部图只用两种颜色就可以完成着色,例如,可以将奇数顶点全部着成颜色1,将偶数顶点全部着成颜色2。

如果贪心法以1,3,…,2n-1,2,4,…,2n的顺序为二部图着色,则算法可以得到这个最优解,但是如果贪心法以1,2,…,n的自然顺序为二部图着色,则算法找到的是一个需要n种颜色的解。

【算法】设数组color[n]表示顶点的着色情况,贪心法求解图着色问题的算法如下:

算法7.4:

贪心法求解图着色问题

输入:

无向连通图G=(V,E)

输出:

最小色数k

1.所有顶点置未着色状态:

2.颜色k初始化为0;

3.循环直到所有顶点均着色

3.1取下一种颜色k++;

3.2依次考察所有顶点:

3.2.1若顶点i已着色,则转步骤3.2,考察下一个顶点;

3.2.2若顶点i着颜色k不冲突,则color[i]=k;

4.输出各顶点的着色;

 

例4最小生成树问题——prim算法

【问题】设G=(V,E)是一个无向连通网,求G的最小生成树。

最小生成树(minimalspanningtree)是各边的权值之和最小的生成树。

【想法】最小生成树问题的贪心策略可以采用最近顶点策略:

任选一个顶点,并以此建立生成树的根结点,每一步的贪心选择是把不在生成树中的最近顶点添加到生成树中。

Prim算法就应用了这个贪心策略,它使生成树以一种自然的方式生长,即从任意顶点开始,每一步为这棵树添加一个分枝,直到生成树中包含全部顶点。

设最小生成树T=(U,TE),初始时U={u0}(u0为任意顶点),TE={}。

显然,Prim算法的关键是如何找到连接U和V-U的最短边来扩充生成树T。

对于每一个不在当前生成树中的顶点v∈V-U,必须知道它连接生成树的最短边信息。

所以,对不在当前生成树中的顶点v∈V-U,需要保存两个信息:

lowcost[v]表示顶点v到生成树中所有顶点的最短边;adjvex[v]表示该最短边在生成树中的顶点。

例如,对于图7.5(a)所示连通网,图7.5(b)~(g)给出了从顶点A出发,用Prim算法构造最小生成树的过程。

 

【算法】设置数组shortEdge[n]表示候选最短边集,数组元素包括adjvex和lowcost两个域,分别表示候选最短边的邻接点和权值,例如,式7-1表明候选最短边(vi,vk)的权值为w,其中vi∈V-U,vk∈U。

假设从顶点w出发构造最小生成树,则初始时,U={w},且shortEdge[w].lowcost=0,表示顶点w已加入集合U中,数组元素shortEdge[i].adjvex=0,shortEdge[i].lowcost=(w,i)的权值(1≤i≤n-1)。

然后在数组shortEdge[n]中不断选取最小权值shortEdge[k].lowcost,将shortEdge[k].lowcost置为0,表示顶点k已加入集合U中。

由于顶点k从集合V-U进入集合U后,候选最短边集发生了变化,依据式7-2更新数组shortEdge的内容:

 

设图G中顶点的编号为0~n-1,Prim算法如下:

算法7.5:

Prim算法

输入:

无向连通网G=(V,E),起始点w

输出:

最小生成树

1.初始化辅助数组shortEdge;

2.U={w};输出顶点w;

3.重复执行下列操作n-1次

3.1在lowcost中选取最短边,取adjvex中对应的顶点序号k;

3.2输出顶点k和对应的权值;

3.3U=U+{k};

3.4调整数组shortEdge;

 

例5最小生成树问题——Kruskal算法

【想法】最小生成树问题的贪心策略可以采用最短边策略:

设最小生成树的边集为TE,最短边策略从TE={}开始,每一次贪心选择都是在边集E中选取最短边(u,v),如果边(u,v)加入集合TE中不产生回路,则将边(u,v)加入边集TE中,并将它在集合E中删去。

Kruskal算法就应用了这个贪心策略,它使生成树以一种随意的方式生长,先让森林中的树木随意生长,每生长一次就将两棵树合并,到最后合并成一棵树。

Kruskal算法对图7.6(a)所示无向连通网构造最小生成树的过程如图7.6(b)~(f)所示,其中,粗边表示已加入边集TE中。

 

【算法2】设图G中顶点的编号为0~n-1,Kruskal算法如下:

算法7.6:

Kruskal算法

输入:

无向连通网G=(V,E)

输出:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1