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;
}
    

 

posted @ 2013-03-22 09:03  煮人为乐  阅读(321)  评论(0编辑  收藏  举报