Codeforces687C-The Values You Can Make(dp)

题目链接

http://codeforces.com/contest/687/problem/C

思路

第一次遇到这种状态表示的dp,转移还是0-1背包,但是状态表示非常重要
可以这样考虑:我们有一个集合A, sum{A}=K ,现在我们从集合A里面选出若干元素,组合一个新的集合B,另 sum{B}=j
对于初始的大集合S里面的每个元素i,我们可以做的就是:
1. 不选入A以及B
2. 选入A但是不选入B
3. 选入A且选入B
那么就可以由此推断出我们的状态表示 d[i][j][k] :前i个元素,选入集合A中的和为k,选入集合B中的和为j是否存在
d[i][j][k]=d[i1][j][k]|d[i1][j][kci]|d[i1][jci][kci];

细节

  1. 滚动数组优化空间
  2. 目标: d[i][j][K]jK

代码

#include <bits/stdc++.h>

using namespace std;

inline int in() {int x; scanf("%d", &x); return x;}
#define pr(x) {cout << #x << ' ' << x << endl;}

const int maxn = 505;
int d[2][maxn][maxn], vis[maxn];
int n, K, c[maxn], tot = 0;

int main() {
    n = in(); K = in();
    for (int i = 1; i <= n; i++) c[i] = in();
    d[0][0][0] = 1;
    for (int i = 1, t = 0; i <= n; i++, t ^= 1) {
        for (int j = 0; j <= 500; j++) {
            for (int k = 0; k <= 500; k++) {
                d[t ^ 1][j][k] = d[t][j][k];
                if (k >= c[i]) d[t ^ 1][j][k] |= d[t][j][k - c[i]];
                if (k >= c[i] && j >= c[i]) d[t ^ 1][j][k] |= d[t][j - c[i]][k - c[i]];
                if (d[t ^ 1][j][k] && k == K && j <= K) 
                    vis[j] = 1;
            }
        }
    }
    for (int i = 0; i <= K; i++)
        if (vis[i]) tot++;
    printf("%d\n", tot);
    for (int i = 0; i <= K; i++) 
        if (vis[i])
            printf("%d ", i);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值