CodeForces 688E-The Values You Can Make
题意:
给出n,k,分别代表硬币的数量与巧克力的价格,n个整数c1,c2,...ci...cn(ci代表第i块硬币的值);你可以从n块硬币中拿出金额恰好为k的硬币数并将其中的任意两块硬币组合得到一个数,将其保存下来(0和输入的n个数的值也必须被保存),最后将这些数按升序排列输出.
分析:
可以采用dp的递推方法,从1到n,dp[i][j]代表通过前i个元素和为i,能否组合出j.
代码如下:
1 #include <cstdio>
2 #include <iostream>
3 #include <ctime>
4 #include <vector>
5 #include <cmath>
6 #include <map>
7 #include <set>
8 #include <stack>
9 #include <queue>
10 #include <algorithm>
11 #include <cstring>
12
13 using namespace std;
14
15 #define LL long long
16 #define INF 0x3f3f3f3f
17 #define MOD 1000000007
18
19 const int maxn = 1e5+5;
20 int a[maxn],n,p;
21 int dp[505][505],tmp[505];
22 vector<int>ret;
23
24 int main()
25 {
26 int i, j, k;
27
28 while(scanf("%d%d",&n, &p)==2)
29 {
30 ret.clear();
31 for(i = 1; i <= n; i++ )
32 scanf("%d", &a[i]);
33 sort(a+1, a+1+n);
34 dp[0][0] = 1; //dp[i][j]代表通过前i个元素和为i,能否组合出j
35 for(i = 1; i <= n; i++ )
36 for(j = p; j >= a[i]; j-- )
37 for(k = 0; k + a[i] <= p; k++ )
38 if(dp[j-a[i]][k])
39 dp[j][k] = dp[j][k+a[i]] = 1;
40 for(i = 0; i <= p; i++ )
41 if(dp[p][i])
42 ret.push_back(i);
43 printf("%d\n", ret.size());
44 for(i = 0; i < ret.size()-1; i++ )
45 printf("%d ", ret[i]);
46 printf("%d\n", ret[ret.size()-1]);
47 }
48
49 return 0;
50 }