52 lines
1.8 KiB
C++
52 lines
1.8 KiB
C++
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
|
||
// 利用循环法进行分组
|
||
const int N = 60, M = 32010;
|
||
|
||
struct Node {
|
||
int w, v;
|
||
};
|
||
|
||
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 w, p, q;
|
||
cin >> w >> p >> q; // 体积,重要度,依赖哪个物品
|
||
if (!q) // 如果是主件
|
||
a[i].push_back({w, w * p}); // 记录主件i的列表中,有了only主件i这个东西
|
||
else
|
||
b[q].push_back({w, w * p}); // 记录主件q的列表中,有了一个附件
|
||
}
|
||
|
||
/*
|
||
比如物品A是1个主件,2个附件,应该最后有4种组合: 主件;主件+附件1;主件+附件2; 主件+附件1+附件2;
|
||
处理办法:
|
||
① 第一步先放主件,把附件先存着;直到主件放完,再去放附件;
|
||
② 循环的放;比如 主件+附件1+附件2=(主件+附件1)+附件2;也就是在前个物品基础之上再加上附件2
|
||
*/
|
||
for (int i = 1; i <= n; i++)
|
||
for (auto c : b[i]) { // 遍历每个附件
|
||
int w = c.w, v = c.v;
|
||
int sz = a[i].size();
|
||
for (int j = 0; j < sz; j++)
|
||
a[i].push_back({a[i][j].w + w, a[i][j].v + v}); // 把扩展出来的组放在尾巴上
|
||
}
|
||
|
||
// 分组背包模板
|
||
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].w)
|
||
f[j] = max(f[j], f[j - a[i][k].w] + a[i][k].v);
|
||
// 输出
|
||
printf("%d\n", f[m]);
|
||
return 0;
|
||
}
|