递推DP URAL 1244 Gentlemen

 

题目传送门

 1 /*
 2     题意:给出少了若干卡片后的总和,和原来所有卡片,问少了哪几张
 3     DP:转化为少了的总和是否能有若干张卡片相加得到,dp[j+a[i]] += dp[j];
 4         记录一次路径,当第一次更新的时候
 5 */
 6 #include <cstdio>
 7 #include <iostream>
 8 #include <algorithm>
 9 #include <cmath>
10 #include <cstring>
11 #include <vector>
12 #include <stack>
13 using namespace std;
14 
15 const int MAXN = 1e5 + 10;
16 const int INF = 0x3f3f3f3f;
17 int a[MAXN];
18 int dp[MAXN];
19 int rt[MAXN];
20 
21 int main(void)        //URAL 1244 Gentlemen
22 {
23     //freopen ("U.in", "r", stdin);
24 
25     int tot, n;
26     while (scanf ("%d", &tot) == 1)
27     {
28         scanf ("%d", &n);
29         int sum = 0;
30         for (int i=1; i<=n; ++i)    {scanf ("%d", &a[i]);    sum += a[i];}
31         if (tot > sum)    {puts ("0");    continue;}
32 
33         memset (rt, 0, sizeof (rt));
34         memset (dp, 0, sizeof (dp));
35         sum -= tot;
36         dp[0] = 1;
37         for (int i=1; i<=n; ++i)
38         {
39             for (int j=sum-a[i]; j>=0; --j)
40             {
41                 if (dp[j] && dp[j+a[i]] == 0)
42                 {
43                     rt[j+a[i]] = i;
44                 }
45                 dp[j+a[i]] += dp[j];
46             }
47         }
48 
49         if (dp[sum] == 0)    {puts ("0");    continue;}
50         else if (dp[sum] == 1)
51         {
52             vector<int> ans;
53             for (int i=n; i>=1; --i)
54             {
55                 if (rt[sum] == i)    {ans.push_back (i);    sum -= a[i];}
56             }
57             for (int i=ans.size ()-1; i>=0; --i)    printf ("%d%c", ans[i], (i==0) ? '\n' : ' ');
58         }
59         else    puts ("-1");
60     }
61 
62     return 0;
63 }

 

posted @ 2015-05-12 16:17  Running_Time  阅读(174)  评论(0编辑  收藏  举报