动态规划——买书问题

转载自CSDN 朱超迪,链接:http://blog.csdn.net/q623702748/article/details/51592427

在朱超迪的原代码上做了一些修改

问题描述:
         在节假日的时候,书店一般都会做促销活动。由于《哈利波特》系列相当畅销,店长决定通过促销活动来回馈读者。上柜的《哈利波特》平装本系列中,一共有五卷。假设每一卷单独销售均需8欧元。如果读者一次购买不同的两卷,就可以扣除5%的费用,三卷则更多。假设具体折扣的情况如下:
 
本数     折扣
2            5%
3           10%
4           20%
5           25%
        
       在一份订单中,根据购买的卷数及本数,就会出现可以应用不同折扣规则的情况。但是,一本书只会应用一个折扣规则。比如,读者一共买了两本卷一,一本卷二。那么,可以享受到5%的折扣。另外一本卷一则不能享受折扣。如果有多种折扣,希望计算出的总额尽可能的低。
         要求根据以上需求,设计出算法,能够计算出读者所购买的一批书的最低价格。
                                                                                  
                                                                                      
思路分析:
         看到这个题目,任何人一开始想到的都是希望让书本尽可能享受高折扣。但是随着书本数目大于5本的时候,享受的总折扣就会相应出现了变化。            
         举个例子, 当输入的数据为(2,2,2,1,1)的时候,如果按照享受最高折扣计算,那么对应的折扣策略就会拆分变成(1,1,1,1,1)和(1,1,1,0,0)两种,总价格变为8×0.75×5+8×0.9×3= 51.6欧元。但是如果我们变一下策略,选择4+4,购买序列变为(1,1,1,1,0)以及(1,1,1,0,1),那么总共花费8×0.8×5+8×0.8×5=51.2欧元。
看到这里,我们已经可以使用动态规划通过计算总折扣数来计算最优惠价格,当然,也可以采用优化的贪心算法来实现,因为贪心算法求解这类题目都是近似解,与最优解相近。
 
解题:
先将现有条件转换一下(用百分比表示书本单价的多少倍):
 
本数
相对于书本单价的百分比
1
100%
2
190%
3
270%
4
320%
5
375%
 
具体说明一下吧:
当只有一本书的时候,没有折扣,所以为100%,即原价8欧元购买;
当有两本不同的书本,享有5%折扣,原本总价为200% ,减掉每本5%折扣,为190%,即15.2欧元;
当有三本不同的书本,享有10%折扣,原本总价为300%,减掉每本10%折扣,为270%,即21.6欧元;
当有四本不同的书本,享有20%折扣,原本总价为400%,减掉每本的20%折扣,为320%,即25.6欧元;
当有五本不同的书本,享有25%折扣,原本总价为500%,减掉每本的25%折扣,为375%,即30欧元;
以上折扣数据存放在minDis[6]中
即minDIs[6] = {0 , 1,1.9 , 2.7 , 3.2 , 3.75 };
根据上述条件描述,我们可以定义出一条状态转移方程(核心):
F[Y1,Y2,Y3,Y4,Y5] = min{   //定量 + 变量  的组合
8*minDis[5]+F(Y1-1,Y2-1,Y3-1,Y4-1,Y5-1),
8*minDis[4]+F(Y1-1,Y2-1,Y3-1,Y4-1,Y5),
8*minDis[3]+F(Y1-1,Y2-1,Y3-1,Y4,Y5),
8*minDis[2]+F(Y1-1,Y2-1,Y3,Y4,Y5),
8*minDis[1]+F(Y1-1,Y2,Y3,Y4,Y5)
}
       其中必须保证Y1>=Y2>=Y3>=Y4>=Y5,这样才不会出现更多的冗余数据。例如:(2,2,2,1,1)和(1,2,1,2,2)虽然不同,但是结果都是一样的。

下面是这个问题的代码(我个人修改过了):

 1  //买书问题
 2
 3     float discount[6] = {0,1,1.9,2.7,3.2,3.75};
 4     float price[6][6][6][6][6] = {0};
 5     int num[6] = { 0 };
 6     for (int i = 1; i <= 5; ++i)
 7         cin >> num[i];
 8     int temp = 0;
 9     bubble_sort(num, 5);
10
11     int num1[6] = { 0 };
12     float arr[6] = { 0 };
13     float min = 0;
14     for (int a5 = 0; a5 <= num[5];++a5)
15     for (int a4 = a5; a4 <= num[4];++a4)
16     for (int a3 = a4; a3 <= num[3]; ++a3)
17     for (int a2 = a3; a2 <= num[2]; ++a2)
18     for (int a1 = a2; a1 <= num[1]; ++a1){
19         if (a5 > 0){
20             num1[5] = a5 - 1;
21             num1[4] = a4 - 1;
22             num1[3] = a3 - 1;
23             num1[2] = a2 - 1;
24             num1[1] = a1 - 1;
25             bubble_sort(num1, 5);
26             arr[5] = 8 * discount[5] + price[num1[1]][num1[2]][num1[3]][num1[4]][num1[5]];
27         }
28         if (a4 > 0){
29             num1[5] = a5;
30             num1[4] = a4 - 1;
31             num1[3] = a3 - 1;
32             num1[2] = a2 - 1;
33             num1[1] = a1 - 1;
34             bubble_sort(num1, 5);
35             arr[4] = 8 * discount[4] + price[num1[1]][num1[2]][num1[3]][num1[4]][num1[5]];
36         }
37         if (a3 > 0){
38             num1[5] = a5;
39             num1[4] = a4;
40             num1[3] = a3 - 1;
41             num1[2] = a2 - 1;
42             num1[1] = a1 - 1;
43             bubble_sort(num1, 5);
44             arr[3] = 8 * discount[3] + price[num1[1]][num1[2]][num1[3]][num1[4]][num1[5]];
45         }
46         if (a2 > 0){
47             num1[5] = a5;
48             num1[4] = a4;
49             num1[3] = a3;
50             num1[2] = a2 - 1;
51             num1[1] = a1 - 1;
52             bubble_sort(num1, 5);
53             arr[2] = 8 * discount[2] + price[num1[1]][num1[2]][num1[3]][num1[4]][num1[5]];
54         }
55         if (a1 > 0){
56             num1[5] = a5;
57             num1[4] = a4;
58             num1[3] = a3;
59             num1[2] = a2;
60             num1[1] = a1 - 1;
61             bubble_sort(num1, 5);
62             arr[1] = 8 * discount[1] + price[num1[1]][num1[2]][num1[3]][num1[4]][num1[5]];
63         }
64         min = arr[1];
65         for (int k = 1; k <= 5;++k)
66             if ((arr[k] < min&&arr[k]>0)||min==0)min = arr[k];
67         price[a1][a2][a3][a4][a5] = min;
68     }
69     cout << price[num[1]][num[2]][num[3]][num[4]][num[5]] << endl;
70     return 0;
71 }

其中bubble_sort是一个基本的冒泡排序算法,由于问题规模有限,我就写了个最简单的冒泡排序,由于比较简单所以这里不再提供。

时间: 2025-01-05 22:15:28

动态规划——买书问题的相关文章

js算法:动态规划-金矿模型与买书问题(附js源码)

本文内容介绍转自博客:通过金矿模型介绍动态规划,后面附上我自己实现的js代码: 经典的01背包问题是这样的: 有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放在包里而物品体积总数不超过包的容量m时,能够得到的最大价值是多少?[对于每个物品不可以取多次,最多只能取一次,之所以叫做01背包,0表示不取,1表示取] 为了用一种生动又更形象的方式来讲解此题,我把此题用另一种方式来描述,如下: 有一个国家,所有的国民都非常老实憨厚,某天他们在自己的国家发现了

(动态规划)6049:买书

描述 小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元. 问小明有多少种买书方案?(每种书可购买多本) 输入 一个整数 n,代表总共钱数.(0 <= n <= 1000) 输出 一个整数,代表选择方案种类 样例输入 样例输入1:20 样例输入2:15 样例输入3:0 样例输出 样例输出1:2 样例输出2:0 样例输出3:0 我の代码 #include <iostream> int pri[5]; int dp[1001]; using namespace s

编程之美之买书问题

拿到这个问题,我的第一反应是用贪心算法,优先满足不同种类多的,这样打的折扣比价多.但是,看了书中的分析发现,* 我们设定的贪心策略实际上是有问题的, ie 在买 5 + 3 本的时候会出错. 看到这里,书上说可以利用改进的贪心算法,感觉如果换了相应的折扣数量,可能又会有不同的结果了.因而,没有深入的研究下去. 既然,贪心算法不可行,那就用动态规划呗. 这里的动态规划思路很简单不过写起来有些复杂.我们这里用到了5维数组, 光是init 就写了好多. 其实我在写的时候,就在想有什么简单一点的方法可以

最少的钱买书

题目一:买书 有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下: 如果单独购买其中一卷,那么可以打9.5折. 如果同时购买两卷不同的,那么可以打9折. 如果同时购买三卷不同的,那么可以打8.5折. 如果小明希望购买第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x.y.z为三个已知整数). 当然,这道题完全可以不用动态规划来解,但是现在我们是要学习动态规划,因此请想想如何用动态规划来做? 答案: 1.过程为一次一次的购买,每一次购买也许只买一

4月14号周二课堂练习:买书最优问题

一.问题提出 书店针对<哈利波特>系列书籍进行促销活动,一共5卷,用编号0.1.2.3.4表示,单独一卷售价8元, 具体折扣如下所示: 本数                   折扣 2                       5% 3                       10% 4                       20% 5                       25% 二.题目要求 1.根据购买的卷数以及本数,会对应不同折扣规则情况.单数一本书只会对应一个折扣

课堂练习-买书价格最低

实验背景 书店针对<哈利波特>系列书籍进行促销活动,一共5卷,用编号0.1.2.3.4表示,单独一卷售价8元, 具体折扣如下所示: 本数 折扣 2 5%         3 10%         4 20%            5 25% 根据购买的卷数以及本数,会对应不同折扣规则情况.单数一本书只会对应一个折扣规则,例如购买了两本卷1,一本卷2,则可以享受5%的折扣,另外一本卷一则不享受优惠.       设计算法能够计算出读者购买一批书的最低价格. 一.设计思想此问题可以折算为如何取余

软件工程——买书折扣问题

1.题目 书店针对<哈利波特>系列书籍进行促销活动一共5卷,用编号0.1.2.3.4表示,单独一卷售价八元,具体折扣如下所示: 本书       折扣 2           5% 3          10% 4          15% 5          20% 根据购买的卷数以及本数,会对应不同折扣规则情况.单数一本书只会对应一个折扣规则,例如购买了两本卷1,一本卷2,则可以享受5%的折扣,另外一本卷一则不享受优惠.设计算法能够计算出读者购买一批书的最低价格. 2.设计思路 根据题目

OpenJudge百炼习题解答(C++)--题4040:买书问题

题: 总时间限制:  1000ms  内存限制:  65536kB 描述 某网上书店举行优惠促销,现有两种优惠策略.策略一是购书总额大于100元的可享受免费送货.策略二是如果购书数量大于3本,则购书总额享受95折优惠(不包括运费).两种优惠策略不能同时享受,最多可选择其中一种优惠策略.运费为20元.小明想在这个网站上买书,请帮他选择最优的优惠策略. 输入 有多行,第一行是买书的种类N(0 <= N <= 100),接下来的N行每行输入一种书目的购买数量M和代价P(P不一定是整数).当N为-1时

买书?买知识?

书是什么? 书籍只是知识的载体. 想要领会知识,还需要付出额外的时间和精力. 书贵么? 买书的几十元其实不算什么,珍贵的是读书的时间和注意力. 一本书只要有一部分内容有价值,有启发,自己收获了经验,最好还能联系实践.获得成长,那么就值回书价了. 如何做? 珍惜自己的时间,读好书,吸收好书内的知识. 同"爱读书.爱成长"的各位共勉!