题目链接
思路:dp【i】【j】代表硬币总数为i,子集和为j。当dp【i】【j】为真时,显然dp[i+a[k]][j]和dp[i+a[k]][j+a[k]]也为真。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1005;
bool dp[maxn][maxn]={false};
int main()
{
int n,m,a[maxn];
vector<int>ans;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
dp[0][0]=true;
for(int k=1;k<=n;++k)
for(int i=m;i>=0;--i)//如果正序的话会导致重复加a【k】,所以逆序
for(int j=0;j<=i;++j)
if(dp[i][j]) dp[i+a[k]][j]=dp[i+a[k]][j+a[k]]=true;
for(int i=0;i<=m;++i)
if(dp[m][i]) ans.push_back(i);
printf("%d\n",ans.size());
for(int i:ans) printf("%d ",i);
}