题目
给你一个钱数val,还有好多不同面值的钞票,这些钞票的数目无限。
要你用这些钞票凑够val,使得所用钞票的数目最少,如果钞票数目最少的答案有多个,则输出尽可能用了小面额钞票的那种方案。
思路
一个完全背包
然后为了使得我们用了尽可能小面额的钞票,我们需要只要在凑钱的时候,尽可能的先用大面值的钞票凑,那么剩下的就是钱数就尽可能小了,也就满足了要求。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 15;
const int INF = 0x3f3f3f3f;
int a[maxn];
int ans[maxn];
int dp[2007];
int pre[2007];
int main()
{
int val;
int n;
while(~scanf("%d", &val))
{
scanf("%d", &n);
for(int i = 1; i <= val; i++)
dp[i] = INF;
dp[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
ans[i] = 0;
}
for(int i = 1; i <= n; i++)
{
for(int j = a[i]; j <= val; j++)
{
if(dp[j - a[i]] + 1 < dp[j])
{
dp[j] = dp[j - a[i]] + 1;
pre[j] = i;
}
else if(dp[j - a[i]] + 1 == dp[j] && a[i] > a[pre[j]])
pre[j] = i;
}
}
if(dp[val] == INF)
{
printf("-1\n");
continue;
}else{
while(dp[val])
{
ans[pre[val]]++;
val -= a[pre[val]];
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i], i == n ? '\n' : ' ');
}
}
return 0;
}