多重背包DP,解法参见背包九讲,转化成01背包,本题数据量小,不用组合物品来优化物品总数,还有DP的时候要保存路径,因为最后要输出。这题一定要注意的是double转int的精度问题!!!参见代码, 我开始时用round方法,明明找来的所有测试数据都能过,结果提交OJ就WA。。肯定有另外的测试数据。。然后参考了大神的代码,学会了另一种转int方式。。
#include<stdio.h>
#include<limits.h>
#include<string.h>
static int min(int a, int b)
{
return a < b ? a : b;
}
int main()
{
double A;
int B, C, D, E, dp[501], pack[300], path[501], res[26];
while (scanf("%lf %d %d %d %d", &A, &B, &C, &D, &E) != EOF)
{
int a = (int) (A * 100.0 + 0.0001), b = min(a / 25, B), c = min(a / 10,
C), d = min(a / 5, D), e = min(a, E);
int i, j, index = 0;
for (i = 0; i < b; i++)
pack[index++] = 25;
for (i = 0; i < c; i++)
pack[index++] = 10;
for (i = 0; i < d; i++)
pack[index++] = 5;
for (i = 0; i < e; i++)
pack[index++] = 1;
dp[0] = 0;
for (i = 1; i <= a; i++)
dp[i] = INT_MAX;
for (i = 0; i < index; i++)
for (j = a; j >= pack[i]; j--)
if (dp[j - pack[i]] != INT_MAX && dp[j - pack[i]] + 1 < dp[j])
{
dp[j] = dp[j - pack[i]] + 1;
path[j] = i;
}
if (dp[a] != INT_MAX)
{
memset(res, 0, sizeof(res));
while (a)
{
res[pack[path[a]]]++;
a -= pack[path[a]];
}
printf("%d %d %d %d\n", res[25], res[10], res[5], res[1]);
}
else
puts("NO EXACT CHANGE");
}
return 0;
}