UVa 147 Dollars 解答

题目描述:

http://uva.onlinejudge.org/external/1/147.html


分析:

1.典型的动态规划题

2.注意浮点型向整数型强制转换的问题,比如299.90*100强制转换成整型可能为29989。小技巧是可以用(n+0.005)*100来解决

3.由于计算结果会超过int型表示范围,所以需要使用long long来保存结果,否则会得到WA委屈


最直接的递推法代码如下:

/*
 * 147.cc
 *
 *  Created on: Jan 7, 2013
 *      Author: root
 */
#include <stdio.h>
#include <string.h>
#include <math.h>

const int TYPE = 11;
int selection[TYPE] = {5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000};
int visit[TYPE+1][30001];
long long value[TYPE+1][30001];

long long dp(int coins, int max) {
	if (coins == 0)
		return 1;
	if (visit[max][coins])
		return value[max][coins];
	long long sum = 0;
	for (int i=0; i<max; i++) {
		if (selection[i] <= coins) {
			sum += dp(coins-selection[i], i+1);
		}
	}
	visit[max][coins] = 1;
	value[max][coins] = sum;
	return value[max][coins];
}

int main(int argc, char** argv) {
	double money;
	memset(visit, 0, sizeof(visit));
	while (scanf("%lf", &money) != EOF) {
		if (fabs(money-0.0) < 1e-7)
			break;
		printf("%6.2lf%17lld\n", money, dp((int) ((money+0.005)*100), TYPE));
	}
	return 0;
}

参考运行结果:

guixl@guixl-ThinkPad-T61:~/workspace/UVa$ g++ -o test 147.cc 
guixl@guixl-ThinkPad-T61:~/workspace/UVa$ ./test < input.txt 
  2.00              293
  5.00             6149
299.90  181000196059736
300.00  181490736388615

变换为动态规划递推法:

/*
 * 147.cc
 *
 *  Created on: Jan 7, 2013
 *      Author: root
 */
#include <stdio.h>
#include <string.h>
#include <math.h>

const int TYPE = 12;
int selection[TYPE] = {0, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000};
long long value[TYPE][30001];

void dp(int coins) {
	for (int i=0; i<TYPE; i++)
		value[i][0] = 1;
	memset(value[0], 0, sizeof(value[0]));

	for (int j=5; j<=coins; j+=5)
		for (int i=1; i<TYPE; i++) {
			long long add = selection[i] > j ? 0 : value[i][j-selection[i]];
			value[i][j] = value[i-1][j] + add;
	}
}

int main(int argc, char** argv) {
	double money;
	while (scanf("%lf", &money) != EOF) {
		if (fabs(money-0.0) < 1e-7)
			break;
		int coins = (int) ((money+0.005)*100);
		dp(coins);
		printf("%6.2lf%17lld\n", money, value[TYPE-1][coins]);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值