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