题面链接:https://codeforces.com/contest/687/problem/C
codeforces difficulty :2000
题意:给定n个硬币每个硬币有a[i]的价值
现在问一个子集的和为x并且这个子集存在与某个构成合为K的子集中。这样的x有多少个并且将x输出。
思路:这题直接开头没想清楚直接写了一发01背包 当能构成i 并且能构成 k-i 时i 为答案。
这样想清楚后发现 i在这种情况下 构成 k-i 和 i 的硬币中 并不独立。简单说就是重合了。实际上无法构成K
n 和 k 的上限均为 500
实际上可对 答案要求直接dp
DP[i][j][k] 表示 前 i 个硬币中构成 j 的子集 并且包含k的情况是否存在
答案即是 DP[n][k][i] 为1的i
转移也很简单关键是要想到方程
#include <bits/stdc++.h>
using namespace std;
int a[505];
char dp[501][501][501];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dp[0][0][0] = 1;
for(int i=1;i<=n;i++){
int num = a[i];
for(int j=0;j<=m;j++){
for(int k=0;k<=j;k++){
dp[i][j][k] = dp[i-1][j][k];
if(j-num>=0 ){
dp[i][j][k] = max(dp[i][j][k],dp[i-1][j-num][k]);
if(k-num>=0) dp[i][j][k] = max(dp[i][j][k],dp[i-1][j-num][k-num]);
}
}
}
}
vector<int> ans;
for(int i=0;i<=m;i++){
if(dp[n][m][i]){
ans.push_back(i);
}
}
cout<<ans.size()<<"\n";
for(auto out:ans){
cout<<out<<" ";
}
return 0;
}