cf687 C. The Values You Can Make(形似01背包)

题意:

求所有的 \(x\),要求存在原集(数组)\(S\) 的一个子集 \(E\)\(E\) 中数的和恰为 \(K\)\(E\) 的某个子集的数之和为 \(x\)

\(1\le n, K, a_i\le 500\)

思路:

\(f(i,j)\) 表示拼出体积 \(i\) 的时候能否拼出体积 \(j\),初值 \(f(0,0)=0\),目标 \(\max\limits _j f(K,j)\)

\(f(i,j)\to f(i+a,j),f(i+a,j+a)\)

注意这是个01背包,为避免做成完全背包,要注意更新顺序

先枚举 \(a[m]\) ,然后倒序更新以保证 \(f(a[1\sim m])(i,j)\) 的值从 \(f(a[1\sim m-1])\)

const int N = 1005;
int n, K, a[N];
bool f[N][N];
main()
{
    cin >> n >> K;
    for(int i = 1; i <= n; i++) cin >> a[i];

    f[0][0] = 1;
    for(int k = 0; k <= n; k++)
        for(int i = K; i >= 0; i--)
            for(int j = K; j >= 0; j--)
                 if(f[i][j])
                    f[i+a[k]][j] = f[i+a[k]][j+a[k]] = 1;

    vector<int> ans;
    for(int i = 0; i <= K; i++) if(f[K][i]) ans.pb(i);
    cout << ans.size() << endl;
    for(int i : ans) cout << i << ' ';
}

posted @ 2022-02-13 17:43  Bellala  阅读(74)  评论(0)    收藏  举报