nyoj-167 找奶牛病毒 “按位或”运算 递归
小珂的工作
时间限制:1000 ms | 内存限制:65535 KB
难度:4“”
描述
小珂有一个奶牛场,奶牛场最近在流行D(1<D<=15)种病毒,小珂的农场一共有N(1<N<=1000)只奶牛,含超过K(1<=K<=D)种病毒的牛奶不得不丢弃.(牛奶中含有奶牛身上的病毒)。现在希望你写一个程序,来确定一下一个桶里的最多可以包含多少头奶牛的牛奶。
输入
第一行一个整数M(1<M<=7),表示有M组测试数据,接下来的M组数据的第一行有三个整数,N,D,K,分别表示奶牛的数量,病毒的总种类,最多一个桶中可以包含的病毒数量。接下来N行,第i行,第一个数 i1,表示第i头牛包含的病毒种类个数,随后i1个数,表示的是病毒种类的标号(默认对D个病毒尽心标号,从1到D ),如果i1 为0,表示第没有病毒。
输出
每组数据输出可以最多挤多少头牛(不换桶),换行结束。
样例输入
1
6 3 2
0
1 1
1 2
1 3
2 2 1
2 2 1
样例输出
5
解题思路:这个题的规律是找包含关系最大的数目。包含关系 用到位运算里面的 |(按位或)运算,当a面包含b这个数,a|b==a;就是如果包含的话,运算后a是不变的。这个题就是用到这个思想。另外就是递归,找出当选择K种病毒时,我们找出此时最多的数量就行。
代码:
View Code
#include<stdio.h> #include<string.h> int bit[20],cow[1001]; int max,n,d,k; void dfs(int at,int num,int all) { //at第几种病毒 num是当前病毒总数 all已经选定的病毒 if(d-at+1<k-num) return ; if(num==k) { int ans=0,i; for(i=0;i<n;++i) { if(cow[i]==(cow[i]&all))//看此时i牛的病是否被包含在已有病毒里面 ans++; } if(ans>max) max=ans; return; } dfs(at+1,num,all);//不选 dfs(at+1,num+1,all|=bit[at]);//选择 } int main() { int i,j,x,T,m; scanf("%d",&T); for(i=0;i<16;++i)//初始bit数组 bit[i]=1<<i; while(T--) { scanf("%d%d%d",&n,&d,&k); memset(cow,0,sizeof(cow)); max=0; for(i=0;i<n;++i) { scanf("%d",&m); for(j=1;j<=m;++j) { scanf("%d",&x); cow[i]|=bit[x];//加入此种牛 } } dfs(1,0,0); printf("%d\n",max); } return 0; }