买书问题
题目:
在节假日的时候,书店一般都会做促销活动。由于《哈利波特》系列相当畅销,店长决定通过促销活动来回馈读者。上柜的《哈利波特》平装书系列中,一共有五卷。假设每一卷单独销售均需8欧元。如果读者一次购买不同的两卷,就可以扣除5%的费用,三卷则更多,假设具体折扣的情况如下:
本数
折扣
2
5%
3
10%
4
20%
5
25%
在一份订单中,根据购买的卷数及本数,就会出现可以应用不同折扣规则的情况。但是,一本书只会应用一个折扣规则。比如,读者一共买了两本卷一,一本卷二。那么,可以享受5%的折扣。另外一本卷一则不能享受折扣。如果有多种折扣,希望计算出的总额尽可能的低。
要求根据以上需求,设计出算法,能够计算出读者所购买一批书的最低价格。
思路:
1. 用动态规划首先需找到递归公式,因为动态规划是由顶向下递归的,自顶向下求解,根据底层结果得到最终解。
2. 5卷数的价格相同,如果用x1...x5对应1~5卷书的本数,F(x1,x2,x3,x4,x5)表费用,那F(x1,x2,x3,x4,x5)=F(x2,x1,x3,x4,x5),根据排列组合,就有5!种表示方法,因此没有必要区分不同的卷,可以让书本按递减(或递增)来表示,(Y1,Y2,Y3,Y4,Y5)是x1,x2,x3,x4,x5的重排列,Y1>=Y2>=Y3>=Y4>=Y5。
3. 递归公式:
F(Y1,Y2,Y3,Y4,Y5)
=0 (当Y1=Y2=Y3=Y4=Y5=0)
=min{
5*8*(1-0.25)+F(Y1-1,Y2-1,Y3-1,Y4-1,Y5-1), (当Y5>=0)
4*8*(1-0.20)+F(Y1-1,Y2-1,Y3-1,Y4-1,Y5), (当Y4>=0)
3*8*(1-0.10)+F(Y1-1,Y2-1,Y3-1,y4,Y5), (当Y3>=0)
2*8*(1-0.05)+F(Y1-1,Y2-1,Y3,Y4,Y5), (当Y2>=0)
8+F(y1-1,y2,y3,y4,y5), (当Y1>=0)
}
实现:
#include#include#define n 5
#define INF 9999
using namespace std;
double min5(double a,double b,double c,double d,double e)//求5个double数的最小值
{
return min(min(min(a,b),min(c,d)),e);
}
double F(int y1,int y2,int y3,int y4,int y5)//递归实现动态规划
{
if(y1+y2+y3+y4+y5==0)return 0;//递归出口
//排序
int p[5]={y1,y2,y3,y4,y5};
sort(p,p+5,[](int a,int b){
return a=1)t5=5*8*(1-0.25)+F(y1-1,y2-1,y3-1,y4-1,y5-1);
if(y4>=1)t4=4*8*(1-0.20)+F(y1-1,y2-1,y3-1,y4-1,y5);
if(y3>=1)t3=3*8*(1-0.10)+F(y1-1,y2-1,y3-1,y4,y5);
if(y2>=1)t2=2*8*(1-0.05)+F(y1-1,y2-1,y3,y4,y5);
if(y1>=1)t1=8+F(y1-1,y2,y3,y4,y5);
//cout<>x[i];
}
sort(x,x+n,[](int a,int b){
return a