Codeforces 687C The Values You Can Make DP

来源:互联网 发布:手机关闭淘宝店铺 编辑:程序博客网 时间:2024/05/16 04:46
题意:全集A为n个a[i],若有某个集合B其和为k,则B的任意一个子集C定义其元素之和x为合法
n,k,c[i]<=500 求出所有合法的x.
设dp[i][j][k] 表示前i个数能凑出子集和为j,和为j的集合又有子集和为k

考虑第i个数是否加入,加入到集合j时,又分是否加入集合j的子集.

dp[i][j][k]|=dp[i-1][j][k]|dp[i-1][j-a[i][k]|dp[i-1][j-a[i]][k-a[i]].

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=5e2+1;int dp[N][N],a[N],n,K;vector<int> ans;int main(){while(cin>>n>>K){for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(dp,0,sizeof(dp));dp[0][0]=1;for(int i=1;i<=n;i++){for(int j=500;j>=0;j--){for(int k=500;k>=0;k--){dp[j][k]|=dp[j][k];if(j>=a[i])dp[j][k]|=dp[j-a[i]][k];if(j>=a[i]&&k>=a[i])dp[j][k]|=dp[j-a[i]][k-a[i]];}}}for(int i=0;i<=K;i++){if(dp[K][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;}