买书问题的实现

这道题首先想到的是贪心,但是很不好分析正确性。算法上讲的,贪心算法需要具有最优子结构和贪心选择的性质,在这里都不好证明。然后就是动态规划了,贴一下我的实现代码,我努力的使代码简洁一些,可还是不太好看。

#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的应该也不差。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值