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
", ans.size());
        for(int i = 0; i < ans.size(); ++i)  if(!i)  printf("%d", ans[i]);
            else  printf(" %d", ans[i]);
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5649740.html