题意:给定 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 ", ans.size()); for(int i = 0; i < ans.size(); ++i) if(!i) printf("%d", ans[i]); else printf(" %d", ans[i]); printf(" "); } return 0; }