我是靠谱客的博主 稳重狗,最近开发中收集的这篇文章主要介绍Coins HDU - 2844(多重背包 模板题),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

http://acm.hdu.edu.cn/showproblem.php?pid=5572

题目大意

有n种面值的硬币,每种硬币有c[i]个,问1~m之间的所有价值,能用这些硬币组合出来的个数是多少个。(1≤n≤100), (m≤100000)

分析

明显的多重背包。把每种硬币二进制拆分优化。
详细看 背包问题整理

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[110], c[110]; // a[i]硬币面值 c[i]硬币个数
int v[1100], tot; // 重新分组后的tot个物品价值
bool f[N];
int main() {
int n, m;
while (cin >> n >> m, n) {
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) cin >> c[i];
tot = 0;
/*对每种面值的硬币二进制拆分 重新分组*/
for (int i = 1; i <= n; ++i) {
int x = 1;
while (c[i] >= x) {
v[++tot] = a[i] * x;
c[i] -= x;
x <<= 1;
}
if (c[i] > 0) v[++tot] = a[i] * c[i];
}
memset(f, false, sizeof(f));
f[0] = true; /*初始化 用任何硬币表示价值为0都为真*/
/*对二进制拆分后的tot个物品01背包*/
for (int i = 1; i <= tot; ++i) {
for (int j = m; j >= v[i]; --j) {
f[j] |= f[j - v[i]];
}
}
int ans = 0;
for (int i = 1; i <= m; ++i) {
ans += f[i];
}
cout << ans << endl;
}
return 0;
}

最后

以上就是稳重狗为你收集整理的Coins HDU - 2844(多重背包 模板题)的全部内容,希望文章能够帮你解决Coins HDU - 2844(多重背包 模板题)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部