算法设计与分析论文_第1页
算法设计与分析论文_第2页
算法设计与分析论文_第3页
算法设计与分析论文_第4页
算法设计与分析论文_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选文档贪心算法不在贪心中爆发,就在贪心中灭亡 武汉理工大学计算机科学与技术学院 班摘要本文介绍贪心算法的基本意义以及算法的使用范围,并通过具体的案例来分析贪心算法的具体应用,从而指出其特点和存在问题。关键字:贪心算法,贪心策略,TSP、0/1背包引言我们用了13周的时间学完了算法设计与分析这本书。这本书中涵盖了大量的常见算法,包括蛮力法、分治法、动态规划法、贪心算法等等。我最有印象的就是贪心算法。贪心算法是一种有合理的数据组织和清晰高效的算法,它简单有效。下面我们来详细解读一下这个算法。1. 贪心算法的含义贪心算法可以简单描述为:对一组数据进行排序,找出最小值,进行处理,再找出最小值,再处理

2、。也就是说贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望得到结果是最好或最优的算法。2. 贪心算法的基本思想贪心算法,法如其名,每次都贪心的选取当前最优解,一旦确定了当前解,不管将来有什么结果,之后都不会再修正,这一点与动态规划法比起来稍有逊色。如果一个问题的最优解只能用蛮力法穷举得到,则贪心法不失为寻找问题近似最优解的一个较好办法。贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中

3、,直到把所有数据枚举完,或者不能再添加算法停止。3. 贪心算法的基本要素3.1 贪心选择贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一

4、步贪心选择,最终可得到问题的一个整体最优解。3.2 最优子结构当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题。4. 贪心算法的核心贪心算法的核心问题是选择能产生问题最优解的最优度量标准,即具体的贪心策略。贪心策略决定着贪心算法是爆发或者是灭

5、亡。所以,选择一个合理、正确的贪心策略是至关重要的。下面用例子说明:第一个例子我们选用大家熟知的0/1背包问题。给定种物品和一个背包。物品的重量是,其价值为,背包的容量为。在选择物品装入背包时,不可以选择物品的一部分,一定要全部装入背包, 。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?设表示物品装入背包的情况,根据问题的要求,有如下约束条件和目标函数: 于是,背包问题归结为寻找一个满足约束条件式,并使目标函数式达到最大的解向量 。现在有一个容量为50的背包,共有三个物品,重量为别为20、30、10,价值分别为60、120、50。现使用贪心算法来放置物品,贪心策略也对应有三种,分别

6、是根据重量、价格、重量与价格比。根据重量的贪心策略,即优先放置重量小的物品,以此来达到放置更多个物品的目的。首先需要将物品按照重量从小到大重新排序,然后从小到大的放置物品,直至下个物品无法放进背包为止。伪代码如下:public class worseGreedy public static void DepWeight(double a, double c, int ans) / depend/ on/ the/ weight to select/ goodsdouble w = new doublea0.length;System.arraycopy(a0, 0, w, 0, w.lengt

7、h);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(w);for (int i = 0; wi <= c && i < w.length; i+) c = c - wi;int j = sea.search(a0, wi);ansj = 1;程序的运行结果见附录。根据价格的贪心策略,即优先放置价格比较高的物品,以此来达到背包价格更高的目的。首先需要将物品按照价格从大到小重新排序,然后依次放置物品,直至下个物品超出背包容量为止。伪代码如下:public static void DepPrice(d

8、ouble a, double c, int ans) / depend on/ the price/ to select goodsdouble p = new doublea1.length;System.arraycopy(a1, 0, p, 0, p.length);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(p);int i = (p.length - 1);int j = sea.search(a1, pi);while (a0j <= c && i >= 0) c = c - a

9、0j;ansj = 1;i-;j = sea.search(a1, pi);程序的运行结果见附录。根据重量与价格比值的贪心策略,即优先放置“性价比”高的物品,以此来达到背包价格最大的目的。首先需要求出各个物品的价格与重量的比值,然后按照这个参数来重新排序物品,价重比高的放前面。最后一次放入物品,直至下个物品超出背包容量为止。伪代码如下:public static void DepWePr(double a, double c, int ans) / depend on/ the/ weight/ and pricedouble w = new doublea0.length; / the we

10、ight of goodsSystem.arraycopy(a0, 0, w, 0, w.length); / copy the arraydouble p = new doublea0.length; / the price of goodsSystem.arraycopy(a1, 0, p, 0, p.length); / copy the arraydouble pw = new doublew.length;for (int i = 0; i < w.length; i+)/ price/weightpwi = pi / wi;double wpw = new double2w.

11、length; / record the table of/ weight and pwSystem.arraycopy(w, 0, wpw0, 0, w.length);System.arraycopy(pw, 0, wpw1, 0, w.length);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(pw);int i = (pw.length - 1);int j = sea.search(wpw1, pwi);while (wpw0j <= c && i >= 0) c = c - wpw

12、0j;ansj = 1;i-;j = sea.search(wpw1, pwi);程序运行结果见附录。根据程序运行的结果,我们分别得到三个答案。放置的物品方案分别为: 、 、 。如此看来,根据价格的贪心策略是最“贪心”的。其实不然,根据价格与重量比值的贪心策略的适应范围更加广阔,效果一般来说也更加的好。本例中受到小数据的局限性,无法发挥出其真正的效果。贪心策略之所以能成为贪心算法的核心,就是因为它决定着贪心算法是爆发还是灭亡,以及爆发的程度。上面的例子用三种不同的贪心策略,结果也截然不同。当扩大问题规模时,这种差距就更加的明显。5. 贪心算法的特点货郎担问题(或称旅行商问题或巡回售货员问题),

13、是NP问题中的著名问题。它通常的提法是:货郎到各村去卖货,再回到出发点处,每村到且仅到一次。为其设计一种路线,使得所用旅行售货的时间最短。建立数学模型时,把村庄设为结点,村庄与村庄之间的路线设为结点之间的带权的边,则货郎担问题转化为在图上寻求最优圈问题。即在加权图上求一个圈使得 贪心算法每选入一边都保证了是当前可选边中权值最小的边,这便是“贪心”的含义。基本思想为首先选择图中任意顶点u,并将u置于顶点集合的子集S中。如果S是顶点集合V的真子集,就继续选择顶点j添加到子集S中, cij是权值最小的边。按照同样的步骤不断进行贪心选择,直到子集S=V为止。此时,选取到的所有的边就构成了一棵最小生成树

14、。伪代码如下:public void find(int distance,int ans)int j=1;/starting cityfor(int i=0;i<distance.length;i+)ansi=j;j=min(distancej-1,ans);private int min(int a,int b)int minN=0;int temp=100;EnumerationSearch sea = new EnumerationSearch();for(int i=0;i<a.length;i+)if(sea.search(b, (i+1)=-1)if(ai<tem

15、p)temp=ai;minN=i;minN+;return minN;程序运行结果见附录。同时我们运用动态规划法来求解同样的问题,问题规模为8个城市。动态求解过程需要使用10ms的时间,而贪心算法只需要使用1ms以内的时间即可完成计算,我们可以理解到贪心算法的爆发力了。但是,它们的结果并不相同。动态规划法求解的答案为:,而贪心算法的答案为:。动态规划法需要走的路程为21,而贪心算法需要走的路程为25。这就是贪心算法的特点,虽快但不一定准。贪心算法每次都是局部寻优,很容易会陷入局部最优解的波谷。所以,贪心算法总结起来一共有三个小缺点。1) 不能保证求得的最后解是最佳的。由于贪心策略总是采用从局部

16、看来是最优的选择,因此并不从整体上加以考虑。2) 贪心算法只能用来求某些最大或最小解的问题。从前面的讨论中,背包问题要求得到最大价值是可行的,但是在另外一个求解最小路径时采用贪心算法得到的结果并不是最佳。3) 贪心算法只能确定某些问题的可行性范围。贪心算法的优点已经提到了,就是快,通常是线性到二次式,不需要多少额外的内存。一般二次方级的存储要浪费额外的空间,而且那些空间经常得不出正解。但是,使用贪心算法时,这些空间可以帮助算法更容易实现且更快执行。如果有正确贪心性质存在,那么一定要采用!因为它容易编写,容易调试,速度极快,并且节约空问。几乎可以说,此时它是所有算法中最好的。6. 结束语贪心算法

17、是很常见的算法,贪心策略是最接近人的日常思维的一种解题策略,虽然它不能保证求得的最后解一定是最佳的,但是它可以为某些问题确定一个可行性范围。贪心算法所作的选择依赖于以往所作过的选择,但决不依赖于将来的选择,这使得算法在编码和执行过程中都有一定的速度优势。对于一个问题的最优解只能用穷举法得到时,用贪心算法是寻找问题最优解的较好算法。对一个问题可以同时用几种方法解决,贪心算法并不是对所有的问题都能得到整体最优解或是最理想的近似解时,就需判断贪心性质的正确性了。与回溯法、动态规划法等比较,它的适用区域相对狭窄许多。总之,如果一个贪心解决方案存在,就使用它。7. 参考文献:1 肖衡.浅析贪心算法J.荆

18、楚理工学院学报.2009.092 常友渠,肖贵元,曾敏.贪心算法的探讨与研究J. 重庆电力高等专科学校学报. 第13卷, 第3期3 汪莹.论贪心算法在图论中的应用J.南京邮电大学学报4 董军军.动态规划算法和贪心算法的比较与分析J.软件导刊. 第7卷 第2期5 林章美.货郎担问题的若干解法J.6 王红梅.算法设计与分析M.北京:清华大学出版社.2006.77 江红,余青松.程序设计教程M.8. 附录源代码:package Algorithm.ZeroPack.Console;import java.util.Scanner;import java.util.Arrays;import Algo

19、rithm.ZeroPack.Greedy.*;public class Console /* * param args */public static void main(String args) / TODO Auto-generated method stubScanner in = new Scanner(System.in);/ input somethingint num; / the number of itemsdouble c; / the capacity of the rucksackSystem.out.println("How big is this ruc

20、ksack capacity?");c = in.nextDouble();System.out.println("How manu items?");num = in.nextInt();int ans1 = new intnum; / the answerint ans2 = new intnum; / the answerint ans3 = new intnum; / the answerfor (int i = 0; i < num; i+) / initializationans1i = 0;ans2i = 0;ans3i = 0;double

21、table = new double2num; / the weight and priceSystem.out.println("please input the table");for (int i = 0; i < num; i+) /input the tableSystem.out.println("The weight of NO." + (i + 1) + " is:");table0i = in.nextDouble();System.out.println("The price of NO."

22、; + (i + 1) + " is:");table1i = in.nextDouble();worseGreedy.DepWeight(table, c, ans1);System.out.println("Depend on the weight"+Arrays.toString(ans1);worseGreedy.DepPrice(table, c, ans2);System.out.println("Depend on the price"+Arrays.toString(ans2);betterGreedy.DepWePr

23、(table, c, ans3);System.out.println("Depend on the weight and price"+Arrays.toString(ans3);System.out.println("over");package Algorithm.ZeroPack.Greedy;import QuickSort.Quick;import Search.EnumerationSearch;public class betterGreedy public static void DepWePr(double a, double c,

24、int ans) / depend on/ the/ weight/ and pricedouble w = new doublea0.length; / the weight of goodsSystem.arraycopy(a0, 0, w, 0, w.length); / copy the arraydouble p = new doublea0.length; / the price of goodsSystem.arraycopy(a1, 0, p, 0, p.length); / copy the arraydouble pw = new doublew.length;for (i

25、nt i = 0; i < w.length; i+)/ price/weightpwi = pi / wi;double wpw = new double2w.length; / record the table of/ weight and pwSystem.arraycopy(w, 0, wpw0, 0, w.length);System.arraycopy(pw, 0, wpw1, 0, w.length);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(pw);int i = (pw.length - 1);

26、int j = sea.search(wpw1, pwi);while (wpw0j <= c && i >= 0) c = c - wpw0j;ansj = 1;i-;j = sea.search(wpw1, pwi);package Algorithm.ZeroPack.Greedy;import QuickSort.Quick;import Search.EnumerationSearch;public class worseGreedy public static void DepWeight(double a, double c, int ans) / d

27、epend/ on/ the/ weight to select/ goodsdouble w = new doublea0.length;System.arraycopy(a0, 0, w, 0, w.length);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(w);for (int i = 0; wi <= c && i < w.length; i+) c = c - wi;int j = sea.search(a0, wi);ansj = 1;public static void Dep

28、Price(double a, double c, int ans) / depend on/ the price/ to select goodsdouble p = new doublea1.length;System.arraycopy(a1, 0, p, 0, p.length);EnumerationSearch sea = new EnumerationSearch();Quick.Sort(p);int i = (p.length - 1);int j = sea.search(a1, pi);while (a0j <= c && i >= 0) c

29、= c - a0j;ansj = 1;i-;j = sea.search(a1, pi);package QuickSort;public class Quick public static void Sort(double a) QuickSort(a,0,a.length-1);private static void QuickSort(double r, int first ,int end)int pivot;if(first<end)pivot=Partition(r,first,end);QuickSort(r,first,pivot-1);QuickSort(r,pivot

30、+1,end);private static int Partition (double r,int first ,int end)int i=first;int j=end;double tmp;while(i<j)while(i<j&&ri<=rj)j-;if(i<j)tmp=ri;ri=rj;rj=tmp;i+;while(i<j&&ri<=rj)i+;if(i<j)tmp=ri;ri=rj;rj=tmp;j-;return i;package Search;public class EnumerationSear

31、ch public int search(double a,double goal)int add=-1;for (int i=0;i<a.length;i+)if (ai=goal)add=i;break;return add;public int search(int a,int goal)int add=-1;for (int i=0;i<a.length;i+)if (ai=goal)add=i;break;return add;package TSP.console;import java.util.Arrays;import TSP.find.*;public class console /* * param args */public static void main(String args) / TODO Auto-generated method stub int distance = /各个节点之间路径长度的二维数组 0, 2, 1, 3, 4, 5, 5, 6, 1, 0, 4, 4, 2, 5, 5, 6, 5, 4, 0, 2, 2, 6, 5, 6, 5, 2, 2,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论