题目链接: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)
第二行从小到大为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,第二行输出空行。
如果不存在必须被使用的硬币,则第一行输出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 }