题意 给你n种面额不同的金币和每种金币的个数 求这些金币能组合成的面额在m内有多少种
还是明显的背包问题 d[i]表示这些金币在i内能组合成的最大面额 初始化d为负无穷 d[0]=0 这样就可以保证d[i]恰好为i时才能为正值
原因可以自己想想 然后就用背包背吧 直接多重背包也可以过 但是分成多重背包和完全背包要快一点
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 105, M = 100005; int main() { int n, m, val[N], num[N], d[M], ans; while (scanf ("%d%d", &n, &m), n && m) { memset (d, 0x8f, sizeof (d)); d[0] = ans = 0; for (int i = 1; i <= n; ++i) scanf ("%d", &val[i]); for (int i = 1; i <= n; ++i) scanf ("%d", &num[i]); for (int i = 1; i <= n; ++i) { if (num[i]*val[i] >= m) for (int j = val[i]; j <= m; ++j) d[j] = max (d[j], d[j - val[i]] + val[i]); else { for (int k = 1; k <= num[i]; k *= 2) { for (int j = m; j >= k * val[i]; --j) d[j] = max (d[j], d[j - k * val[i]] + k * val[i]); num[i] -= k; } if (num[i] > 0) for (int j = m; j >= num[i]*val[i]; --j) d[j] = max (d[j], d[j - num[i] * val[i]] + num[i] * val[i]); } } for (int i = 1; i <= m; ++i) if (d[i] > 0) ++ans; printf ("%d\n", ans); } return 0; }
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
8 4
HDU 2844 Coins (组合背包),布布扣,bubuko.com
原文地址:http://blog.csdn.net/iooden/article/details/38469877