题意:有十一种面值的钱币,给出一个数额<=300$的钱数,问用这些面值的钱构成有多少种不同的方法。
分析:完全背包。递推DP。由于题目给出的是两位小数,所以可以乘以一百转化成整数,那么最大的数额变成30000。注意到题目给出的面值都是5的倍数,所以可以全部除以5转化成1,2,3,10,20....,最大的数额也由30000缩小到了6000,是一个很大的改进。 注意精度的处理。还有答案可能是个很大的数,应该用long long int。
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#define eps 1e-9
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int maxn=6010;
long long dp[20][6010];
int val[]={1,2,4,10,20,40,100,200,400,1000,2000};
int main()
{
double x;
int V;
for(int i=0;i<maxn;i++) dp[0][i]=1;
for(int i=1;i<11;i++){
for(int j=0;j<maxn;j++){
for(int k=0;k*val[i]<=j;k++)
dp[i][j]+=dp[i-1][j-k*val[i]];
}
}
while(scanf("%lf",&x)==1){
if(x<=eps) break;
V=(int)(x*100+0.5)/5;
printf("%6.2lf%17lld\n",x,dp[10][V]);
}
return 0;
}