疾病管理
Description
最近在农夫 John 的农场上有 D(1<=D<=15) 种疾病 ( 疾病的编号为 1..D) 在奶牛当中流行。 John 想要给他的 N(1<=N<=1000) 头奶牛挤牛奶。 挤出来的牛奶都被放在一个罐子里面。 如果这些牛奶中包含了超过 K(1<=K<=D) 种的疾病, 那么这些牛奶就要全部被丢弃掉了 。 John 应该给这 N 头奶牛当中的哪些奶牛挤奶, 才能使得牛奶不被丢弃, 并且挤牛奶的数量最多呢?
Input
第一行: 三个整数 N,D 和 K
接下来有 N 行: 这当中的第 i 行描述了第 i 个奶牛得病的信息。 第一个数字 p , 表示第 i 头奶牛得了 p 种病, 接下来有 p 个数字表示这些病的编号。 如果 p 等于 0 , 表明这头奶牛很健康。
Output
输出 John 最多可以给多少头奶牛挤牛奶。
Sample Input
6 3 2
0
1 1
1 2
1 3
2 2 1
2 2 1
Sample Output
5
Hint
John 最多可以给 5 头奶牛挤牛奶。 他们的编号分别为 1,2,3,5,6. 此时这些牛奶中只包含 2种疾病, 编号为 1, 2 。 疾病种数不超过 K=2 。
Source
搜索, 动态规划,状态压缩
Solution
状态压缩
枚举每一头奶牛,并用之更新每一种中毒的情况
f[j|num[i]] = max(f[j|num[i]], f[j] + 1);
这也就是这道题的转移方程,当前情况下不重复的中毒情况(所以用“|”)Code
#include <cstdio>
#include <algorithm>
#include <cmath>
#define L (1 << 15)
#define LL long long
using namespace std;
int n, d, k, q, cnt, a, maxx, ans;
int f[L], num[L];
inline int lowbit(int x) {
return x & (-x);
}
inline bool check(int x) {
cnt = 0;
for (int i = x; i; i -= lowbit(i)) cnt++;
if (cnt <= k) return 1;
return 0;
}
int main() {
freopen("disease.in", "r", stdin);
freopen("disease.out", "w", stdout);
scanf("%d %d %d", &n, &d, &k);
for (int i = 1; i <= n; ++i) {
scanf("%d", &q);
for (int j = 1; j <= q; ++j) scanf("%d", &a), num[i] += (1 << (a - 1));
}
for (int i = 1; i <= n; ++i)
for (int j = (1 << d) - 1; j >= 0; j--)
f[j|num[i]] = max(f[j|num[i]], f[j] + 1);
for (int j = 0; j < (1 << d) - 1; j++)
if (check(j)) maxx = max(f[j], maxx);
printf("%d\n", maxx);
return 0;
}
Summary
这是考试的题
考试的时候只有40分,状压打萎了
之后把状态更新的顺序及方式修改了一下就A了