poj 2436 Disease Management
http://poj.org/problem?id=2436
问题描述:n个奶牛携带至多d种病毒,最多选出多少头奶牛使得携带病毒的种类不超过k种?
思路: 状态压缩+位运算
位运算真的很神奇,很容易想到将每一头奶牛的患病情况抽象成一串二进制序列,0011表示携带第一二种病毒,压缩成十进制用位运算的|来判断,怎么判断呢,如果枚举所有牛的组合会有2^N ->2 ^ 100种情况,每种情况按位或|再判断复杂度太高?!!!
可以暴力结果,最终的结果无非是0000~1111(如果d = 4的话,注意是d不是k),其中1的个数超过k的排除掉,假设状态为x,与每一头牛的情况|,若x==x|row[i]说明第i头牛最终落到这种x状态,累加起来取最大值即可,复杂度O(n×2^d)
参考代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<sstream>
#define eps 1e-9
#define pi acos(-1)
#define long long ll
#define M 10
#define N 1010
using namespace std;
const int _max = 170 + 10;
int x,m,n,d,k,row[N];
bool judge(int x){
int ans = 0;
while(x){
if(x&1) ans++;
x>>=1;
}
return (ans<=k);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif // ONLINE_JUDGE
while(~scanf("%d%d%d",&n,&d,&k)){
for(int i = 1; i <= n; ++ i){
row[i] = 0;
scanf("%d",&m);
for(int j = 0; j < m; ++ j){
scanf("%d",&x);
row[i]^=1<<(x-1);//状态压缩
}
}
int ans,tar = -1;
for(int i = 0; i < (1<<d); ++ i){
if(!judge(i)) continue;
ans = 0;
for(int j = 1; j <= n; ++ j)
if((i|row[j]) == i) ans++;
if(tar < ans) tar = ans;
}
printf("%d\n",tar);
}
return 0;
}
- 加粗
Ctrl + B
- 斜体
Ctrl + I
- 引用
Ctrl + Q
- 插入链接
Ctrl + L
- 插入代码
Ctrl + K
- 插入图片
Ctrl + G
- 提升标题
Ctrl + H
- 有序列表
Ctrl + O
- 无序列表
Ctrl + U
- 横线
Ctrl + R
- 撤销
Ctrl + Z
- 重做
Ctrl + Y