题目描述:
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;
}