E. The Values You Can Make
题意
Pari 从自己的n个硬币中给了Arya K元钱,现在他想知道Arya能用这k元钱凑出哪些钱数。
思路
dp[i][j][k]表示前i个硬币中,给Arya总共j元钱,Arya能否凑出k元钱。
于是Pari选择把第i+1个硬币不给Arya则
dp[i+1][j][k]|=dp[i][j][k];
而Pari给出后,Arya可以选择是否去凑。
dp[i+1][j+a[i+1]][k]|=dp[i][j][k];
dp[i+1][j+a[i]][k+a[i]]|=dp[i][j][k];
code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN (500 + 5)
int n, k;
int c[MAXN];
bool dp[MAXN][MAXN][2];
int main () {
ios::sync_with_stdio(false);
cin >> n >> k;
for (int i=1; i<=n; i++) {
cin >> c[i];
}
dp[0][0][0] = true;
int sum = 0;
for (int v=1; v<=n; v++) {
for (int i=0; i<=min(sum, k); i++) {
for (int j=0; j<=min(k, sum); j++) {
if (dp[i][j][(v+1)%2] == false) continue;
dp[i][j][v%2] = dp[i][j][(v+1)%2];
if (i + c[v] > k) continue;
if (j + c[v] <= k) dp[i + c[v]][j + c[v]][v%2] = true;
dp[i + c[v]][j][v%2] = true;
}
}
sum += c[v];
}
int cnt = 0;
for (int i=0; i<=k; i++) {
if (dp[k][i][n%2] == false) continue;
cnt++;
}
cout << cnt << endl;
for (int i=0; i<=k; i++) {
if (dp[k][i][n%2] == 0) continue;
cout << i << " ";
}
cout << endl;
return 0;
}