/*
买书问题:
过程:
接受输入,对输入按照从大到小排序(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; }