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 << ' ';
}

浙公网安备 33010602011771号