day9基于贪心的算法和应用举例-杨志军.pptVIP

  • 26
  • 0
  • 约7.8千字
  • 约 47页
  • 2017-06-26 发布于湖北
  • 举报

day9基于贪心的算法和应用举例-杨志军.ppt

day9基于贪心的算法和应用举例-杨志军

经典例题 【例5】均分纸牌(NOIP 2002) 有N堆纸牌,编号分别为1,2,……,N。第i堆有a[i]张纸牌(a[i]≤10000),但纸牌总数必为N的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为1堆上取的纸牌,只能移到编号为2的堆上;在编号为N的堆上取的纸牌,只能移到编号为N-1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆牌数都一样多。 经典例题 例如:N=4,纸牌数分别为9、8、17、6,移动3次可达到目的。 第一次:从第3堆取4张牌放到第4堆; 9、8、13、10 第二次:从第3堆取3张牌放到第2堆; 9、11、10、10 第三次:从第2堆取1张牌放到第1堆。 10、10、10、10 经典例题 【分析】 设v为均分后每堆纸牌的张数,s为最少移动次数。按照从左到右的顺序移动纸牌。如果第i堆的纸牌数a[i]不等于v,则移动一次,分两种情况移动: (1)如果a[i]v,则将a[i]-v张纸牌从第i堆移动到第i+1堆; (2)如果a[i]v,则将v-a[i]张纸牌从第i+1堆移动第i堆。 经典例题 【分析】 从第i+1堆中取出纸牌给第i堆的过程中,可能会出现第i+1堆的纸牌数小于0的情况。如n=3,三堆纸牌数为1、2、27,v=10,要从第2堆移动9张纸牌到第1堆,而第2堆只有2张纸牌可以移动。按照规则会得到10、-7、27,再从第3堆移动17张纸牌到第2堆,即得到10、10、10。在移动过程中,只要改变一下移动的顺序,而移动的次数不会变。 经典例题 参考程序 readln(n); v:=0; for i:=1 to n do begin read(a[i]); v:=v+a[i]; end; v:=v div n; s:=0; for i:=1 to n-1 do if a[i]v then begin inc(s); a[i+1]:=a[i+1]+a[i]-v; end; writeln(s); 讨论二 【例6】合并果子(NOIP 2004) 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。 讨论二 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。 例如有3种果子,数目依次为1,2,9。可以先将1,2堆合并,新堆数目为3,耗费体力为3,接着,将新堆与原先的第3堆合并,又得到新的堆,数目为12,耗费体力为12,所以多多总共耗费体力为15。 讨论二 【分析】 为了使最终的体力耗费值最小,应该每一次都选择最小的两堆果子合并,使每次合并耗费的体力值最小。 算法过程: (1)读入每堆果子的数目; (2)将果子数目按递增顺序进行排序; (3)合并数目最少的两堆果子,并增加体力耗费值; (4)在果子序列中删除合并的两堆果子数目,增加合并后的果子数目; (5)重复步骤2-4,直到所有果子合并为一堆; (6)输出体力耗费值。 讨论二 【分析】 上面的方法需要进行n-1次排序,比较浪费时间,可以用空间换时间的思路,另设一个数组存放每次合并后的堆。 先读入n堆果子的数目a,并按递增顺序进行排列,得到一个序列a[1]……a[n]。 再设另一个数组b,从a、b的第一个元素开始找合并方案: (1)a数组的两个元素合并; (2)a和b数组的一个元素合并; (3)b数组的两个元素合并。 将合并后的值放入b数组。 参考程序 p:=0; x:=1; y:=1; total:=0; for i:=1 to n-1 do begin min:=maxlongint; if a[x]+a[x+1]min then begin min:=a[x]+a[x+1]; t:=1; end; if a[x]+b[y]min then begin min:=a[x]+b[y]; t:=2; end; if b[y]+b[y+1]min

文档评论(0)

1亿VIP精品文档

相关文档