/*
买书问题:
过程:
接受输入,对输入按照从大到小排序(a,b,c,d,e),然后选取min,设置递归出口是全0
输入:
2 1 1 1 1
2 2 2 1 1
2 2 2 2 2
10 10 10 10 10
输出:
38.0
51.2
60.0
300.0
*/
/*
关键:
1 int _iCostArr[MAXSIZE][MAXSIZE][MAXSIZE][MAXSIZE][MAXSIZE];//用作记忆化搜索,原来可以设置5维数组
2 void my_sort(int& a,int& b,int& c,int& d,int& e)//注意这些值返回后继续用的,所以要用引用
a = _iSortArr[0];//注意再重新返回a,因此形参要用引用
3 my_sort(a,b,c,d,e);//按照从大到小排序
int& iRet = _iCostArr[a][b][c][d][e];//注意,这里使用引用,可以提高速度,并且会用iRes为cost赋值
if(iRet != -1)//记忆化搜索,如果已经求解过,就直接返回,避免重复递归
{
return iRet;
4 if(a >= 1 && b < 1)//如果只剩下一个种类的书了,那么最大值自然就是,没有优惠,自己付钱
5 else if(a >= 1 && e >= 1)//a,b,c,d,e均有剩余,可以享受7.5折
{
return iRet = min(5*8*75 + buyBook(a-1,b-1,c-1,d-1,e-1), 4*8*80 + buyBook(a-1,b-1,c-1,d-1,e) ,
3*8*90 + buyBook(a-1,b-1,c-1,d,e),2*8*95 + buyBook(a-1,b-1,c,d,e) ,
800 + buyBook(a-1,b,c,d,e));
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <assert.h>
using namespace std;
const int MAXSIZE = 15;
int _iCostArr[MAXSIZE][MAXSIZE][MAXSIZE][MAXSIZE][MAXSIZE];//用作记忆化搜索,原来可以设置5维数组
int _iSortArr[5];
bool compare(int a,int b)
{
return a > b;
}
void my_sort(int& a,int& b,int& c,int& d,int& e)//注意这些值返回后继续用的,所以要用引用
{
_iSortArr[0] = a;
_iSortArr[1] = b;
_iSortArr[2] = c;
_iSortArr[3] = d;
_iSortArr[4] = e;
sort(_iSortArr,_iSortArr+5,compare);
a = _iSortArr[0];//注意再重新返回a,因此形参要用引用
b = _iSortArr[1];
c = _iSortArr[2];
d = _iSortArr[3];
e = _iSortArr[4];
}
int min(int a,int b)
{
return a < b ? a : b;
}
int min(int a,int b,int c)
{
return min( min(a,b),c);
}
int min(int a,int b,int c,int d)
{
return min(min(a,b),min(c,d));
}
int min(int a,int b,int c,int d,int e)
{
return min( e,min( min(a,b) , min(c,d) ) );
}
int buyBook(int a,int b,int c,int d,int e)
{
assert(a >= 0 && b >= 0 && c >= 0 && d >= 0 && e >=0);
if(!a && !b && !c && !d && !e)//递归出口,如果每本书都是0本,那么最少的价钱自然是0
{
return 0;
}
my_sort(a,b,c,d,e);//按照从大到小排序
int& iRet = _iCostArr[a][b][c][d][e];//注意,这里使用引用,可以提高速度,并且会用iRes为cost赋值
if(iRet != -1)//记忆化搜索,如果已经求解过,就直接返回,避免重复递归
{
return iRet;
}
//我们应该从最大的开始算,要不然就不好求最小值了
if(a >= 1 && b < 1)//如果只剩下一个种类的书了,那么最大值自然就是,没有优惠,自己付钱
{
return iRet = (800 + buyBook(a-1,b,c,d,e));
}
else if(a >= 1 && b >= 1 && c < 1)//如果a与b均剩余,其余三类书空了,可以享受95折
{
return iRet = min( 2*8*95 + buyBook(a-1,b-1,c,d,e) , 800 + buyBook(a-1,b,c,d,e));
}
else if(a >= 1 && c >= 1 && d < 1)//如果a,b,c均有剩余,可享受9折
{
return iRet = min( 3*8*90 + buyBook(a-1,b-1,c-1,d,e), 2*8*95 + buyBook(a-1,b-1,c,d,e) ,
800 + buyBook(a-1,b,c,d,e) );
}
else if(a >= 1 && d >= 1 && e < 1)//a,b,c,d,均剩余,可享受8折
{
return iRet = min( 4*8*80 + buyBook(a-1,b-1,c-1,d-1,e) , 3*8*90 + buyBook(a-1,b-1,c-1,d,e),
2*8*95 + buyBook(a-1,b-1,c,d,e) , 800 + buyBook(a-1,b,c,d,e));
}
else if(a >= 1 && e >= 1)//a,b,c,d,e均有剩余,可以享受7.5折
{
return iRet = min(5*8*75 + buyBook(a-1,b-1,c-1,d-1,e-1), 4*8*80 + buyBook(a-1,b-1,c-1,d-1,e) ,
3*8*90 + buyBook(a-1,b-1,c-1,d,e),2*8*95 + buyBook(a-1,b-1,c,d,e) ,
800 + buyBook(a-1,b,c,d,e));
}
else
{
}
}
int butBook_memory(int a,int b,int c,int d,int e)//记忆化搜索,说白了就是剪枝,可以避免递归的效率降下
{
assert(a >= 0 && b >= 0 && c >= 0 && d >= 0 && e >=0);
if(!a && !b && !c && !d && !e)//递归出口,如果每本书都是0本,那么最少的价钱自然是0
{
return 0;
}
}
void process()
{
int i = 0;
while(EOF != scanf("%d %d %d %d %d",&_iSortArr[i],&_iSortArr[i+1],&_iSortArr[i+2],
&_iSortArr[i+3],&_iSortArr[i+4]))
{
memset(_iCostArr,-1,sizeof(_iCostArr));
int iRes = buyBook(_iSortArr[i],_iSortArr[i+1],_iSortArr[i+2],
_iSortArr[i+3],_iSortArr[i+4]);
printf("%.1f\n",iRes*1.0/100.0);
}
}
int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}