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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}