题目传送门
1 /*
2 题意:已知丢失若干卡片后剩余的总体积,并知道原来所有卡片的各自的体积,问丢失的卡片的id
3 DP递推:首先从丢失的卡片的总体积考虑,dp[i] 代表体积为i的方案数,从dp[0] = 1递推,累加的条件是dp[j]上一个状态已经有方案,
4 若dp[w] > 1表示有多种方案,外加p[j+a[i]] = i的记录路径数组
5 我开始用了暴力DFS超时,dp不会写,看了题解发现是个递推,有点像01背包的题目:)
6 详细解释:http://blog.csdn.net/neko01/article/details/10033787
7 */
8 #include <cstdio>
9 #include <iostream>
10 #include <algorithm>
11 #include <cstring>
12 #include <string>
13 #include <cmath>
14 using namespace std;
15
16 const int MAXN = 1e2 + 10;
17 const int MAXM = 1e6 + 10;
18 const int INF = 0x3f3f3f3f;
19 int a[MAXN];
20 int p[MAXM];
21 int ans[MAXN];
22 int dp[MAXM];
23
24 int main(void) //URAL 1244 Gentlemen
25 {
26 //freopen ("L.in", "r", stdin);
27
28 int w, n, sum;
29 while (scanf ("%d", &w) == 1)
30 {
31 sum = 0;
32 scanf ("%d", &n);
33 for (int i=1; i<=n; ++i)
34 {
35 scanf ("%d", &a[i]); sum += a[i];
36 }
37
38 memset (p, 0, sizeof (p));
39 memset (dp, 0, sizeof (dp));
40 dp[0] = 1; w = sum - w;
41
42 for (int i=1; i<=n; ++i)
43 {
44 for (int j=w-a[i]; j>=0; --j)
45 {
46 if (dp[j])
47 {
48 if (!dp[j+a[i]]) p[j+a[i]] = i;
49 dp[j+a[i]] += dp[j];
50 }
51 }
52 }
53
54 int cnt = 0;
55 if (dp[w] == 0) puts ("0");
56 else if (dp[w] == 1)
57 {
58 for (int i=n; i>=1; --i)
59 {
60 if (p[w] == i)
61 {
62 ans[++cnt] = i;
63 w -= a[i];
64 }
65 }
66
67 for (int i=cnt; i>=1; --i)
68 {
69 printf ("%d%c", ans[i], (i==1) ? '
' : ' ');
70 }
71 }
72 else puts ("-1");
73 }
74
75 return 0;
76 }