Bundles of Joy
.
.
题意:给定m个包裹,n个蛋糕,每个包裹包含一些蛋糕以及所需要的费用,保证包裹之间蛋糕集合只会出现包含或者相离的关系,问买完所有蛋糕的最小花费(蛋糕不能买重复)。
.
.
解法:类似拓扑序。因为只有包含或者无关,所以对于每一个包裹,看能否被前面所有被他包含的包裹的花费更新,如果可以就更新,最后求出全集的花费。
.
.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
using namespace std;
struct Node {
int cost;
int num;
bool a[200];
bool operator<(Node& other) {
return num < other.num;
}
}f[200];
int count[200], n, m, x, y;
bool flag[200], b[200];
int main() {
int tt;
scanf("%d", &tt);
while (tt--) {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
memset(f[i].a, 0, sizeof(f[i].a));
scanf("%d", &f[i].cost);
scanf("%d", &f[i].num);
for (int j = 1; j <= f[i].num; j++) {
scanf("%d", &x);
f[i].a[x] = true;
}
}
m++;
f[m].cost = 1000000000;
f[m].num = n;
for (int i = 1; i <= n; i++) f[m].a[i] = true;
sort(f+1, f+m);
memset(flag, 0, sizeof(flag));
for (int i = 2; i <= m; i++) {
int sum = 0;
memset(b, 0, sizeof(b));
for (int j = 1; j < i; j++) if (!flag[j]) {
bool belong = false;
for (int k = 1; k <= n; k++) if (f[i].a[k] && f[j].a[k]) {
belong = true;
break;
}
if (belong) {
flag[j] = true;
for (int k = 1; k <= n; k++) b[k] = b[k] || f[j].a[k];
sum = sum+f[j].cost;
}
}
bool equal = true;
for (int k = 1; k <= n; k++) if (b[k] != f[i].a[k]) {
equal = false; break;
}
if (equal) {
if (sum < f[i].cost) f[i].cost = sum;
}
}
printf("%d\n", f[m].cost);
}
}