这道题首先想到的是贪心,但是很不好分析正确性。算法上讲的,贪心算法需要具有最优子结构和贪心选择的性质,在这里都不好证明。然后就是动态规划了,贴一下我的实现代码,我努力的使代码简洁一些,可还是不太好看。
#include <iostream>
#include <cstdlib>
#include <cstring>
using std::cin;
using std::cout;
using std::endl;
double res[20][20][20][20][20];
const double discount[5] = {0, 0.05, 0.1, 0.2, 0.25};
template <class T>
int comp(const void *a, const void *b){
return *(T*)b - *(T*)a;
}
double get_min(double* a, int length){
qsort(a, length, sizeof(double), comp<double>);
return a[length-1];
}
double find_best(int a, int b, int c, int d, int e){
int num[5] = {a, b, c, d, e};
qsort(num, 5, sizeof(int), comp<int>);
if(num[0] == 0)
return 0.0;
a = num[0]; b = num[1]; c = num[2]; d = num[3]; e = num[4];
if(res[a][b][c][d][e]>0)
return res[a][b][c][d][e];
double tp[5], t_res;
memset(tp, 0, sizeof(tp));
int length = 0;
if(e>0){
tp[4] = find_best(a-1, b-1, c-1, d-1, e-1);
tp[3] = find_best(a-1, b-1, c-1, d-1, e);
tp[2] = find_best(a-1, b-1, c-1, d, e);
tp[1] = find_best(a-1, b-1, c, d, e);
tp[0] = find_best(a-1, b, c, d, e);
length = 5;
}else if(d>0){
tp[3] = find_best(a-1, b-1, c-1, d-1, e);
tp[2] = find_best(a-1, b-1, c-1, d, e);
tp[1] = find_best(a-1, b-1, c, d, e);
tp[0] = find_best(a-1, b, c, d, e);
length = 4;
}else if(c>0){
tp[2] = find_best(a-1, b-1, c-1, d, e);
tp[1] = find_best(a-1, b-1, c, d, e);
tp[0] = find_best(a-1, b, c, d, e);
length = 3;
}else if(b>0){
tp[1] = find_best(a-1, b-1, c, d, e);
tp[0] = find_best(a-1, b, c, d, e);
length = 2;
}else{
tp[0] = find_best(a-1, b, c, d, e);
length = 1;
}
for(int i=0;i<length;i++){
tp[i] += (i+1)*8.0*(1-discount[i]);
}
t_res = get_min(tp, length);
res[a][b][c][d][e] = t_res;
return t_res;
}
int main(){
int num[5];
while(true){
for(int i=0;i<5;i++){
cin>>num[i];
}
cout<<find_best(num[0], num[1], num[2], num[3], num[4])<<endl;
}
}
其他的我不说了,因为只是把书上的式子实现而已。5维数组开销太大,而且最后存的都是排序之后的,里面空元素太多。想了一下可以用map,键是排序好的书数目,值是最小的价钱。效率方面,数组是O(1)的时间,map的应该也不差。