Codeforces Round #360 (Div. 2) E The Values You Can Make(DP)

时间:2021-08-04 18:41:21

题意:问你凑出K的所有子集C之和

思路:令dp[i][j][k]为用第i个凑出j的子集之和为k是否可行

           然后dp[i][j][k]|=dp[i-1][j][k],dp[i][j][k]|=dp[i-1][j-c][k],dp[i][j][k]|=dp[i-1][j-c][k-c]直接搞就好了

注意:会爆内存,改用bool或者滚动数组就好了

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 1000100
#define MOD 1000000007

int n,m;
bool dp[505][505][505];

int main()
{
    int t;
    //scanf("%d",&t);
    while(scanf("%d%d",&n,&m) != EOF)
    {
        memset(dp,0,sizeof(dp));
        dp[0][0][0] = 1;
        for(int i = 1; i <= n; i++)
        {
            int x;
            scanf("%d",&x);
            for(int j = 0; j <= 500; j++)
                for(int k = 0; k <= 500; k++)
            {
                dp[i][j][k] |= dp[i-1][j][k];
                if(j >= x)
                    dp[i][j][k] |= dp[i-1][j-x][k];
                if(j >= x && k >= x)
                    dp[i][j][k] |= dp[i-1][j-x][k-x];
            }
        }
        vector<int> ans;
        for(int i = 0; i <= 500; i++)
            if(dp[n][m][i])
                ans.push_back(i);
        printf("%d\n",ans.size());
        for(int i = 0; i < ans.size(); i++)
            printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}