CoderForces 687C The Values You Can Make (01背包,DP)

时间:2023-03-09 16:38:27
CoderForces 687C The Values You Can Make (01背包,DP)

题意:给定 n 个硬币和一个值 k,问你在用一些硬币组成面值为 k的这些硬币还能组成多少种其他面值。

析:如果这样说,由这些硬币能组成多少种不同的面值,那么是不是就很熟悉了,这不就是01背包么,这个题又加了一个限制条件,是用能组成 k 的这些硬币,也是类似的,d[i][j],表示硬币 j 能组成面值 i,

那么如果再加一个硬币x,d[i+x][j]也是可以的,d[i+x][j+x]也是可以的,所以如果d[i][j]成立,那么d[i+x][j],和d[i+x][j+x]也是成立的。

代码如下:

#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std;
const int maxn = 500 + 5;
vector<int> ans;
bool d[maxn][maxn]; int main(){
int n, k, x;
while(scanf("%d %d", &n, &k) == 2){
ans.clear();
memset(d, 0, sizeof(d));
d[0][0] = true;
for(int i = 0; i < n; ++i){
scanf("%d", &x);
for(int j = k; j >= x; --j)
for(int l = 0; l + x <= k; ++l)
if(d[j-x][l]) d[j][l] = d[j][l+x] = true;
}
for(int i = 0; i <= k; ++i) if(d[k][i]) ans.push_back(i);
printf("%d\n", ans.size());
for(int i = 0; i < ans.size(); ++i) if(!i) printf("%d", ans[i]);
else printf(" %d", ans[i]);
printf("\n");
}
return 0;
}