贪心算法学习总结.doc_第1页
贪心算法学习总结.doc_第2页
贪心算法学习总结.doc_第3页
贪心算法学习总结.doc_第4页
贪心算法学习总结.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

贪心算法一、算法思想贪心法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。该算法存在问题:1. 不能保证求得的最后解是最佳的;2. 不能用来求最大或最小解问题;3. 只能求满足某些约束条件的可行解的范围。实现该算法的过程:从问题的某一初始解出发;while 能朝给定总目标前进一步 do 求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;二、例题分析1、背包问题有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。物品ABCDEFG重量wi35306050401025价值pi10403050354030分析:目标函数: pi最大约束条件是装入的物品总重量不超过背包容量:wi=fj thenbegin a ai;j:=i;endend;例1 找零钱 一个小孩买了价值少于1美元的糖,并将1美元的钱交给售货员。售货员希望用数目最少的硬币找给小孩。假设提供了数目不限的面值为2 5美分、1 0美分、5美分、及1美分的硬币。售货员分步骤组成要找的零钱数,每次加入一个硬币。选择硬币时所采用的贪婪准则如下:每一次选择应使零钱数尽量增大。为保证解法的可行性(即:所给的零钱等于要找的零钱数),所选择的硬币不应使零钱总数超过最终所需的数目。 假设需要找给小孩6 7美分,首先入选的是两枚2 5美分的硬币,第三枚入选的不能是2 5美分的硬币,否则硬币的选择将不可行(零钱总数超过6 7美分),第三枚应选择1 0美分的硬币,然后是5美分的,最后加入两个1美分的硬币。 贪婪算法有种直觉的倾向,在找零钱时,直觉告诉我们应使找出的硬币数目最少(至少是接近最少的数目)。可以证明采用上述贪婪算法找零钱时所用的硬币数目的确最少(见练习1)。 例2 机器调度 现有n 件任务和无限多台的机器,任务可以在机器上得到处理。每件任务的开始时间为si,完成时间为fi ,si k。寻找 1 ,n范围内最小的整数j,使得xjyj 。若没有这样的j 存在,则n i= 1xi =n i = 1yi 。如果有这样的j 存在,则jk,否则y 就不是一个可行解,因为xjyj ,xj = 1且yj = 0。令yj = 1,若结果得到的y 不是可行解,则在 j+ 1 ,n范围内必有一个l 使得yl = 1。令yl = 0,由于wjwl ,则得到的y 是可行的。而且,得到的新y 至少与原来的y 具有相同数目的1。 经过数次这种转化,可将y 转化为x。由于每次转化产生的新y 至少与前一个y 具有相同数目的1,因此x 至少与初始的y 具有相同的数目1。货箱装载算法的C + +代码实现见程序1 3 - 1。由于贪婪算法按货箱重量递增的顺序装载,程序1 3 - 1首先利用间接寻址排序函数I n d i r e c t S o r t对货箱重量进行排序(见3 . 5节间接寻址的定义),随后货箱便可按重量递增的顺序装载。由于间接寻址排序所需的时间为O (nl o gn)。 程序13-1 货箱装船 template void ContainerLoading(int x, T w, T c, int n) / 货箱装船问题的贪婪算法 / xi = 1 当且仅当货箱i被装载, 1=i=n / c是船的容量, w 是货箱的重量 / 对重量按间接寻址方式排序 / t 是间接寻址表 int *t = new int n+1; I n d i r e c t S o r t ( w, t, n); / 此时, wti = wti+1, 1=in / 初始化x for (int i = 1; i = n; i+) xi = 0; / 按重量次序选择物品 for (i = 1; i = n & wti = c; i+) xti = 1; c -= wti; / 剩余容量 delete t; 背包问题 在0 / 1背包问题中,需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即n i=1pi xi 取得最大值。约束条件为n i =1wi xic 和xi 0 , 1 ( 1in)。 在这个表达式中,需求出xt 的值。xi = 1表示物品i 装入背包中,xi =0 表示物品i 不装入背包。0 / 1背包问题是一个一般化的货箱装载问题,即每个货箱所获得的价值不同。货箱装载问题转化为背包问题的形式为:船作为背包,货箱作为可装入背包的物品。 例1-8 在杂货店比赛中你获得第一名,奖品是一年免费杂货,店中有n种不同的货物。规则规定从每种货物中最多只能拿一件,车子的容量为c,物品i 需占用wi 的空间,价值为pi 。你的目标是使车中装载的物品价值最大。当然,所装货物不能超过车的容量,且同一种物品不得拿走多件。这个问题可仿照0 / 1背包问题进行建模,其中车对应于背包,货物对应于物品。 0 / 1背包问题有好几种贪婪策略,每个贪婪策略都采用多步过程来完成背包的装入。在每一步过程中利用贪婪准则选择一个物品装入背包。一种贪婪准则为:从剩余的物品中,选出可以装入背包的价值最大的物品,利用这种规则,价值最大的物品首先被装入(假设有足够容量),然后是下一个价值最大的物品,如此继续下去。这种策略不能保证得到最优解。例如,考虑n=2, w=100,10,10, p =20,15,15, c = 1 0 5。当利用价值贪婪准则时,获得的解为x= 1 , 0 , 0 ,这种方案的总价值为2 0。而最优解为 0 , 1 , 1 ,其总价值为3 0。 另一种方案是重量贪婪准则是:从剩下的物品中选择可装入背包的重量最小的物品。虽然这种规则对于前面的例子能产生最优解,但在一般情况下则不一定能得到最优解。考虑n= 2 ,w=10,20, p=5,100, c= 2 5。当利用重量贪婪策略时,获得的解为x =1,0, 比最优解 0 , 1 要差。 还可以利用另一方案,价值密度pi /wi 贪婪算法,这种选择准则为:从剩余物品中选择可 装入包的pi /wi 值最大的物品,这种策略也不能保证得到最优解。利用此策略试解n= 3 ,w=20,15,15, p=40,25,25, c=30 时的最优解。 我们不必因所考察的几个贪婪算法都不能保证得到最优解而沮丧, 0 / 1背包问题是一个N P-复杂问题。对于这类问题,也许根本就不可能找到具有多项式时间的算法。虽然按pi /wi 非递(增)减的次序装入物品不能保证得到最优解,但它是一个直觉上近似的解。我们希望它是一个好的启发式算法,且大多数时候能很好地接近最后算法。在6 0 0个随机产生的背包问题中,用这种启发式贪婪算法来解有2 3 9题为最优解。有5 8 3个例子与最优解相差1 0 %,所有6 0 0个答案与最优解之差全在2 5 %以内。该算法能在O (nl o gn)时间内获得如此好的性能。我们也许会问,是否存在一个x (x1 0 0 ),使得贪婪启发法的结果与最优值相差在x%以内。答案是否定的。为说明这一点,考虑例子n =2, w = 1 ,y, p= 1 0 , 9y, 和c= y。贪婪算法结果为x=1,0, 这种方案的值为1 0。对于y1 0 / 9,最优解的值为9 y。因此,贪婪算法的值与最优解的差对最优解的比例为( ( 9y - 1 0)/9y* 1 0 0 ) %,对于大的y,这个值趋近于1 0 0 %。但是可以建立贪婪启发式方法来提供解,使解的结果与最优解的值之差在最优值的x% (x100) 之内。首先将最多k 件物品放入背包,如果这k 件物品重量大于c,则放弃它。否则,剩余的容量用来考虑将剩余物品按pi /wi 递减的顺序装入。通过考虑由启发法产生的解法中最多为k 件物品的所有可能的子集来得到最优解。 例13-9 考虑n =4, w=2,4,6,7, p=6,10,12,13, c = 11。当k= 0时,背包按物品价值密度非递减顺序装入,首先将物品1放入背包,然后是物品2,背包剩下的容量为5个单元,剩下的物品没有一个合适的,因此解为x = 1 , 1 , 0 , 0 。此解获得的价值为1 6。 现在考虑k = 1时的贪婪启发法。最初的子集为 1 , 2 , 3 , 4 。子集 1 , 2 产生与k= 0时相同的结果,考虑子集 3 ,置x3 为1。此时还剩5个单位的容量,按价值密度非递增顺序来考虑如何利用这5个单位的容量。首先考虑物品1,它适合,因此取x1 为1,这时仅剩下3个单位容量了,且剩余物品没有能够加入背包中的物品。通过子集 3 开始求解得结果为x = 1 , 0 , 1 , 0 ,获得的价值为1 8。若从子集 4 开始,产生的解为x = 1 , 0 , 0 , 1 ,获得的价值为1 9。考虑子集大小为0和1时获得的最优解为 1 , 0 , 0 , 1 。这个解是通过k= 1的贪婪启发式算法得到的。 若k= 2,除了考虑k0时总的时间开销为O (nk+1 )。实际观察到的性能要好得多。-找零钱问题的贪心算法问题描述: 当前有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少) 问题分析: 根据常识,我们到店里买东西找钱时,老板总是先给我们最大面值的,要是不够再找面值小一点的,直到找满为止。如果老板都给你找分数的或者几角的,那你肯定不干,另外,他也可能没有那么多零碎的钱给你找。其实这就是一个典型的贪心选择问题。 问题的算法设计与实现: 先举个例子,假如老板要找给我99分钱,他有上面的面值分别为25,10,5,1的硬币数,为了找给我最少的硬币数,那么他是不是该这样找呢,先看看该找多少个25分的, 99253,好像是3个,要是4个的话,我们还得再给老板一个1分的,我不干,那么老板只能给我3个25分,由于还少给我24,所以还得给我2个10分的和4个1分。 具体实现 /找零钱算法 /By falcon /输入:数组m,依次存放从大到小排列的面值数,n为需要找的钱数,单位全部为分 /输出:数组num,对照数组m中的面值存放不同面值的硬币的个数,即找钱方案比如要找N分钱,先拿N除最大零钱面值,可以取模得出余数。 当然取整就是所找的最大面值零钱的个数。 所得余数再次处理,用的是一个循环结构。 N输入取值 M是定义的面值M0是最大面值 K是一个数组,存储各面值零钱的个数 i=0 do while (N0) K0=int(N/Mi) N=mod(N,Mi) i+ end do-贪心算法背包问题解题报告 问题描述:假定有n个物体和一个背包,物体i 有质量wi,价值为pi,而背包的载荷能力为M。若将物体i的一部分xi(1=i=n,0=xi=1)装入背包中,则有价值pi*xi。在约束条件(w1*x1+w2*x2+wn*xn)=M下使目标(p1*x1+p2*x2+pn*xn)达到极大,此处0=xi0,1=i=n.这个问题称为背包问题(Knapsack problem)。贪心算法的基本思想:贪心法是一种改进了的分级处理方法。用贪心法设计算法的特点是一步一步地进行,根据某个优化测度(可能是目标函数,也可能不是目标函数),每一步上都要保证能获得局部最优解。每一步只考虑一个数据,它的选取应满足局部优化条件。若下一个数据与部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加为止。这种能够得到某种度量意义下的最优解的分级处理方法称为贪心法。假设有一个能装入总体积为T的背包和n件体积分别为w1 , w2 , , wn 的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1 +w2 + + wn=T,要求找出所有满足上述条件的解。例如:当T=10,各件物品的体积1,8,4,3,5,2时,可找到下列4组解:(1,4,3,2) (1,4,5) (8,2) (3,5,2)。 问题补充:提示:可利用回溯法的设计思想来解决背包问题。首先将物品排成一列,然后顺序选取物品装入背包,假设已选取了前i 件物品之后背包还没有装满,则继续选取第i+1件物品,若该件物品“太大”不能装入,则弃之而继续选取下一件,直至背包装满为止。但如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入背包的那件物品“不合适”,应将它取出“弃之一边”,继续再从“它之后”的物品中选取,如此重复,直至求得满足条件的解,或者无解。 由于回溯求解的规则规则是“后进先出”因此自然要用到栈。 测试数据T=10 各物体体积1,8,4,3,5,2 T=20 各物体体积2,10,7,16,5,4,9,1 问题分析:要想得到最优解,就要在效益增长和背包容量消耗两者之间寻找平衡。也就是说,总应该把那些单位效益最高的物体先放入背包。程序代码:#include struct goodinfo float p; /物品效益 float w; /物品重量 float X; /物品该放的数量 int flag; /物品编号; /物品信息结构体 void Insertionsort(goodinfo goods,int n) int j,i; for(j=2;jgoodsi.p) goodsi+1=goodsi; i-; goodsi+1=goods0; /按物品效益,重量比值做升序排列void bag(goodinfo goods,float M,int n) float cu; int i,j; for(i=1;i=n;i+) goodsi.X=0; cu=M; /背包剩余容量 for(i=1;icu)/当该物品重量大与剩余容量跳出 break; goodsi.X=1; cu=cu-goodsi.w;/确定背包新的剩余容量 if(i

温馨提示

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

评论

0/150

提交评论