河南多校大一训练赛 G 硬币

题目链接:http://acm.hust.edu.cn/vjudge/contest/125004#problem/G

密码:acm

Description

宇航员Bob有一天来到火星上,他有收集硬币的习惯。于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2… an。 Bob在机场看到了一个特别喜欢的礼物,想买来送给朋友Alice,这个礼物的价格是X元。Bob很想知道为了买这个礼物他的哪些硬币是必须被使用的,即Bob必须放弃收集好的哪些硬币种类。飞机场不提供找零,只接受恰好X元。

Input

第一行包含两个正整数n和x。(1 <= n <= 200, 1 <= x <= 10000) 
第二行从小到大为n个正整数a1, a2, a3 … an (1 <= ai <= x)

Output

第一行是一个整数,即有多少种硬币是必须被使用的。 
第二行是这些必须使用的硬币的面值(从小到大排列)。

Sample Input

5 18
1 2 3 5 10

Sample Output

2
5 10

Hint

输入数据将保证给定面值的硬币中至少有一种组合能恰好能够支付X元。 
如果不存在必须被使用的硬币,则第一行输出0,第二行输出空行。
 
分析:好久没写背包题了,得补被背包了~~~~(>_<)~~~~ 
 
 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 #define N 12000
 9 
10 int dp[N],ans[N],num[N],a[N];
11 
12 int main()
13 {
14     int n,x,i,j,cnt=0;
15 
16     while(scanf("%d%d", &n,&x) != EOF)
17     {
18         for(i=1;i<=n;i++)
19             scanf("%d", &a[i]);
20 
21         dp[0]=1;
22         for(i=1;i<=n;i++)
23             for(j=x;j>=a[i];j--)
24             dp[j]=dp[j]+dp[j-a[i]];///dp[i]表示凑成i元钱的方案数
25 
26         for(i=1;i<=n;i++)
27         {
28             memset(ans,0,sizeof(ans));///ans[i]表示不用i号硬币就能凑成x元钱的方案数
29             for(j=0;j<=x;j++)
30             if(j-a[i]>=0)
31                 ans[j]=dp[j]-ans[j-a[i]];
32             else
33                 ans[j]=dp[j];
34             if(ans[x]==0)///凑不成,则是必须使用的硬币
35                 num[cnt++]=a[i];
36         }
37 
38         printf("%d
", cnt);
39         if(cnt==0)
40             printf("
");
41         else
42         {
43             for(i=0;i<cnt;i++)
44             {
45                 if(i==cnt-1)
46                    printf("%d
", num[i]);
47                 else
48                     printf("%d ", num[i]);
49             }
50         }
51     }
52     return 0;
53 }
 
 
原文地址:https://www.cnblogs.com/weiyuan/p/5726045.html