有个人去买书,买不同的本数有不同的折扣,一共有5种书,买的书种类不同,本数越多折扣越高,折扣表如下:
本数 1 2 3 4 5 折扣 0 0.05 0.1 0.2 0.25
买两本不同的书将得到2*0.05的折扣,3本得到3*0.1。问怎样设计一个买书方案使得要买n本书的时候获得的折扣最高?
贪心算法在这里不适用,因为如果每次都是选择最大折扣的话可能获得不了最优解。如要买8本的话用贪心得到的是5+3的方
案,而事实上两个4本比5+3获得的折扣要高。
既然贪心不行,那么我们就考虑动态规划方法吧。动态规划适合以下场景。
- 1.每个问题可以变为若干最优子问题
- 2.子问题之间求解有大量的重复计算
对于条件1,我们每得到一个要买的书本数n,他都可以转化为max{(n-i)+disount[i]}的问题,同时在计算过程中较低的最优解必然会
在较高的最优解中重复用到。可以反证如果不是的话我们最终得到的就不是最优解,因为有折扣更大的方案。
实现如下:
#include <iostream>
using namespace std;
float best[9];
float discount[5]={0,0.1,0.3,0.8,1.25};
float max(float x,float y)
{
return x>y?x:y;
}
float bestChoice(int n)
{
if(best[n-1]!=-1)
return best[n-1];
float temp=0;
for(int i=1;i<=5;i++)
temp=max(bestChoice(n-i)+discount[i-1],temp);
best[n-1]=temp;
return temp;
}
int main()
{
int i;
float temp;
for(i=0;i<5;i++)
best[i]=discount[i];
for(i=5;i<9;i++)
best[i]=-1;
temp=bestChoice(8);
cout<<temp<<endl;
}