题意:
输入的第一行为一个正整数N(1<=N<=40)。下面有N行输入数据,每一行第一个数t为找零的总数,后面6个数字m1,m2, m3, m4, m5, m6分别为现有面值为50,20,10,5,2,1纸币的张数。 如果能够找出总数为t的零钱,那么输出最少的张数的方案。如 s1 s2 s3 s4 s5.分别表示为找零面值为50 20 10 5 2 1的张数。si si+1之间用空格
隔开s5后面没有空格。否则输出Refuse。每个输出占一行。
分析:显然背包的容量为 T ,即选择满足容量的最小解。首先对于设 F[i] 表示在背包容量为 i 的情况下的最优解是 cnt[i][0--5]。则F[i]=max(F[i],F[i-w[j]]+w[j]); 如果 F[i]不变,则跟新cnt[i][0--5];
1
#include<iostream>
2
using namespace std;
3
const int maxn=100000;
4
5
int s[6];
6
int val[6]=
{50,20,10,5,2,1};
7
int v,cnt[maxn][6];
8
int f[maxn];
9
10
int main()
11

{
12
int i,j,k,t,t1,t2;
13
scanf("%d",&t);
14
while(t--)
15
{
16
scanf("%d",&v);
17
for(i=0;i<6;i++)
18
scanf("%d",&s[i]);
19
20
memset(f,0,sizeof(f));
21
memset(cnt,0,sizeof(cnt));
22
23
for(i=0;i<=v;i++)
24
{
25
for(j=0;j<6;j++)
26
{
27
if(i<val[j])continue;
28
29
if(cnt[i-val[j]][j]+1<=s[j])
30
{
31
if(f[i]<f[i-val[j]]+val[j])
32
{
33
f[i]=f[i-val[j]]+val[j];
34
35
for(k=0;k<6;k++)
36
cnt[i][k]=cnt[i-val[j]][k];
37
cnt[i][j]++;
38
}
39
else if(f[i]==f[i-val[j]]+val[j])
40
{
41
t1=0;t2=1;
42
for(k=0;k<6;k++)
43
{
44
t1+=cnt[i][k];
45
t2+=cnt[i-val[j]][k];
46
}
47
if(t2<t1)
48
{
49
for(k=0;k<6;k++)
50
cnt[i][k]=cnt[i-val[j]][k];
51
cnt[i][j]++;
52
}
53
}
54
}
55
}
56
}
57
if(f[v]!=v)
58
{
59
printf("Refuse\n");
60
}
61
else
62
{
63
for(i=0;i<5;i++)
64
printf("%d ",cnt[v][i]);
65
printf("%d\n",cnt[v][5]);
66
}
67
}
68
return 0;
69
}