“买书问题”的贪心算法证明!

本文探讨了买书问题的贪心算法及其证明过程,通过详细的步骤展示如何利用贪心策略达到最优折扣配置。

《编程之美》之1.4 “买书问题”的贪心算法证明。

对买书问题有变形的贪心算法证明:
算法如下:
1.         对给定要买的书籍书卷的数量按小到大排序,不妨设书卷(A,B,C,D,E)的各自购买数量为(x1,x2,x3,x4,x5)(x1<=x2<=x3<=x4<=x5).
2.         按照贪心算法得到有 【5】本书享受折扣 x1 次,【4】本享受x2-x1次, 【3】有x3-x2次,【2】有x4-x3次,【1】有x5-x4次。
3.         享受【5】本折扣{A,B,C,D,E}和【3】任意折扣{B,D,E}的总是能分拆成两份【4】折扣{A,B,D,E},{B,C,D,E}。故将第2步中所得的【5】x1,【3】x3-x2,合并入【4】折扣中.      {如x3-x2<=x1则新的折扣布局为【5】x1-x3+x2,【4】x2-x1+2*(x3-x2),【3】0,【2】x4-x3,【1】x5-x4.}
4.         按上述计算全部折扣。
 
        算法证明:设要购买y本书,并且按最优折扣有【5】y5,【4】y4,【3】y3,【2】y2,【1】y1。现在来考察最优折扣的解得结构。
          因为【5】+【3】总能拆分成【4】+【4】并且【4】+【4】=1.6>【5】+【3】.故在最优折扣中y5和y3必然有一个为0(或两个都为0)
        现在分情况讨论
 
y5=0.考察,【5】y5=0,【4】y4,【3】y3,【2】y2,【1】y1。                                          
【1】y1的集合中卷数必然只有一种(若有两重卷 书则够成【2】折扣),不妨设其为E。                                                      
 
【2】y2的集合中卷数必然只有两种(【3】+【1】>【2】+【2】),并且其中一种为卷E。不妨设为D,E。
 
同理:【3】y3集合中卷数种类只有三种,并包含D,E。不妨设为C,D,E.
 
【4】中可有五种卷,但其只能是{A,C,D,E},{B,C,D,E}类型折扣。若有不包含{CDE}型的折扣(如ABCD)则可与【3】中的CDE合并分拆成【5】+【2】>【4】+【3】.
 
这样就得到了:

 
A
B
C
D
E
【5】
0
0
0
0
0
【4】
XA
XB
y4
y4
y4
【3】
 
 
y3
y3
y3
【2】
 
 
 
y2
y2
【1】
 
 
 
 
y1

         {A,B,C,D,E}的数量为(XA,XB,y3+y4,y3+y4+y2,y4+y3+y2+y1), 其中XA+XB=y4.
        可知当书卷C数量y3+y4>= XA+XB=y4书卷A+B的数量时,用上述变形的贪心算法恰好得到最优折扣的解。
    
      当y5!=0,y3=0时候:考察,【5】y5,【4】y4,【3】y3=0,【2】y2,【1】y1。的结构。
【1】y1的集合中卷数必然只有一种(若有两重卷书则够成【2】折扣),不妨设其为卷E。                                                        
【2】y2的集合中卷数必然只有两种(【3】+【1】>【2】+【2】),并且其中一种为卷E。不妨设为D,E。
 
【3】y3=0。
 
【4】y4的集合中折扣类型必然都包含{D,E}。故为Z1{BCDE},Z2{ACDE},Z3{ABDE},其中Z1+Z2+Z3=y4。
现在证明【4】中只能有两种折扣类型。(反证法)
若有三种 则有{BCDE}+{ACDE}+{ABDE}={ABCDE}+{ABCDE}+{DE}
但是折扣模型【4】+【4】+【4】<【5】+【5】+【2】所以与最优解矛盾。
故【4】y4中的折扣类型最多只能有两种。不妨设其为Z1{BCDE},Z2{ACDE}
其中Z1+Z2=y4.    
 
【5】y5的集合为{A,B,C,D,E}。
 
现在有

 
A
B
C
D
E
【5】
y5
y5
y5
y5
y5
【4】
Z1
Z2
y4
y4
y4
【3】
 
 
0
0
0
【2】
 
 
 
y2
y2
【1】
 
 
 
 
y1

        {A,B,C,D,E}的数量分别为(y5+Z1,y5+Z2,y5+y4,y5+y4+y2,y4+y5+y2+y1), 其中 Z1+Z2=y4。当卷A+卷B数量y5+Z1+y5+Z2=2*y5+y4>y5+y4卷C的数量时候,最优折扣模型也可由上述变形的 贪心算法得到。
   综合上述,算法正确!
    代码:(假设数组a已经按小到大排序)
       float Optimize_ discount(int a[],int n=5)
             {
               If(a[0]>=a[2]-a[1])
{
return (a[0]+a[1]-a[2])*5*25%+(a[1]-a[0]+2a[2]-2a[1])*20%+(a[3]-a[2])*5%; }
               else
                  { return (a[1]-a[0]+2*a[0])*20%+(a[2]-a[1]-a[0])*10%+(a[3]-a[2])*5%;}
             }
买书问题 dp实现 题目:买书 有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下: 如果单独购买其中一卷,那么可以打9.5折。 如果同时购买两卷不同的,那么可以打9折。 如果同时购买三卷不同的,那么可以打8.5折。 如果小明希望购买第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x、y、z为三个已知整数)。 1、过程为一次一次的购买,每一次购买也许只买一本(这有三种方案),或者买两本(这也有三种方案), 或者三本一起买(这有一种方案),最后直到买完所有需要的书。 2、最后一步我必然会在7种购买方案中选择一种,因此我要在7种购买方案中选择一个最佳情况。 3、子问题是,我选择了某个方案后,如何使得购买剩余的书能用最少的钱?并且这个选择不会使得剩余的书为负数 。母问题和子问题都是给定三卷书的购买量,求最少需要用的钱,所以有"子问题重叠",问题中三个购买量设置为参数, 分别为i、j、k。 4、的确符合。 5、边界是一次购买就可以买完所有的书,处理方式请读者自己考虑。 6、每次选择最多有7种方案,并且不会同时实施其中多种,因此方案的选择互不影响,所以有"子问题独立"。 7、我可以用minMoney[i][j][k]来保存购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。 8、共有x * y * z个问题,每个问题面对7种选择,时间为:O( x * y * z * 7) = O( x * y* z )。 9、用函数MinMoney(i,j,k)来表示购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱,那么有: MinMoney(i,j,k)=min(s1,s2,s3,s4,s5,s6,s7),其中s1,s2,s3,s4,s5,s6,s7分别为对应的7种方案使用的最少金钱: s1 = 60 * 0.95 + MinMoney(i-1,j,k) s2 = 60 * 0.95 + MinMoney(i,j-1,k) s3 = 60 * 0.95 + MinMoney(i,j,k-1) s4 = (60 + 60) * 0.9 + MinMoney(i-1,j-1,k) s5 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s6 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s7 = (60 + 60 + 60) * 0.85 + MinMoney(i-1,j-1,k-1)
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值