#include using namespace std; // 利用循环法进行分组 const int N = 60, M = 32010; struct Node { int w, v; }; int n, m; vector a[N]; // 主件 vector 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; }