You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

52 lines
1.8 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
// 利用二进制枚举进行分组
const int N = 60, M = 32010;
struct Node {
int v, w;
};
int n, m;
vector<Node> a[N]; // 主件
vector<Node> b[N]; // 附件
int f[M];
int main() {
cin >> m >> n; // 总钱数,希望购买物品的个数
for (int i = 1; i <= n; i++) {
int v, p, q;
cin >> v >> p >> q; // 价格,重要度,主件还是附件
if (!q)
a[i].push_back({v, p * v}); // q==0,主件第i个物品是主未入库体积是v,价格是p*v
else
b[q].push_back({v, p * v}); // q>0附件它的主件是q,需要维护主件附件的关系b[q].add(附件)
}
// 利用二进制枚举,生成分组的所有组合情况
for (int i = 1; i <= n; i++) {
if (!a[i].size()) continue; // 只讨论主件,由主件进行构建
for (int j = 0; j < 1 << b[i].size(); j++) { // 主件i的所有附件组合情况,比如 000,001,010,...,111
int v = a[i][0].v, w = a[i][0].w; // 主件体积和主件价值
for (int k = 0; k < b[i].size(); k++) // 主件i的所有附件
if (j >> k & 1) v += b[i][k].v, w += b[i][k].w; // 此数字描述多少个数位是1
// 组合的一种情况
a[i].push_back({v, w});
}
}
// 分组背包模板
for (int i = 1; i <= n; i++)
for (int j = m; j >= 0; j--)
for (int k = 0; k < a[i].size(); k++) // 注意这里k是从0开始因为vector的特点决定
if (j >= a[i][k].v)
f[j] = max(f[j], f[j - a[i][k].v] + a[i][k].w);
// 输出
printf("%d\n", f[m]);
return 0;
}