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.

85 lines
3.0 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;
/**
7. 有依赖的背包
1题目
这种背包问题的物品间存在某种“依赖”的关系。
也就是说i依赖于j表示若选物品i则必须选物品j。
为了简化起见,我们先设没有某个物品既依赖于别的物品,又被别的物品所依赖;
另外,没有某件物品同时依赖多件物品。
2输入
测试用例数
物品数 背包大小
第i个物品的ci wi di(依赖物品的编号,-1为不依赖其他物品)
*/
#define maxV 1000
#define maxG 100
int main(void) {
int cases, n, v, ci[maxV], wi[maxV], di, f[maxV];
freopen("../7.txt", "r", stdin);
cin >> cases;
while (cases--) {
memset(f, 0, sizeof(f));
cin >> n >> v;
// group[i]空表示i号物品有依赖因此存放到其他组里
// 只有一个元素表示i号物品既无依赖也不被依赖
// 有多个元素表示i号物品被依赖这里自己的编号i也被存放进group[i]
vector<vector<int> > groups(n);
// 读入数据并储存起来
for (int i = 0; i < n; i++) {
cin >> ci[i] >> wi[i] >> di;
if (di == -1) groups[i].push_back(i);
else groups[di].push_back(i);
}
// 对每个有多个元素的组进行01背包
for (int i = 0; i < n; i++) {
if (groups[i].size() > 1) {
vector<int> giOri; //group[i]的拷贝排除i本身
int newV = v - ci[i];
// 复制group[i]中的元素排除i
for (int j = 0; j < groups[i].size(); j++) {
if (groups[i][j] != i)
giOri.push_back(groups[i][j]);
}
// 把等效物品组存入group[i]中
groups[i].clear();
groups[i].resize(newV + 1, 0);
for (int j = 0; j < giOri.size(); j++) {
for (int k = newV; k >= 0; k--) {
if (ci[giOri[j]] <= k) {
groups[i][k] = max(groups[i][k], groups[i][k - ci[giOri[j]]] + wi[giOri[j]]);
}
}
}
}
}
// 进行分组背包
for (int i = 0; i < n; i++) {
if (groups[i].size() == 0) continue;
else if (groups[i].size() == 1) { // i物品无依赖且不被依赖
for (int j = v; j >= 0; j--) {
if (j >= ci[i])
f[j] = max(f[j], f[j - ci[i]] + wi[i]);
}
} else { // i物品被依赖, i组第k个物品的cost为k + ci[i], weight为group[i][k] + wi[i]
for (int j = v; j >= 0; j--) {
for (int k = 0; k < groups[i].size(); k++) {
if (j >= k + ci[i])
f[j] = max(f[j], f[j - k - ci[i]] + groups[i][k] + wi[i]);
}
}
}
}
cout << f[v] << endl;
}
}