POJ 2436

思路:需要用到位运算,D最为16,用一个int数(32位 > 16位,足够表示)的每个二进制位表示病毒的存在与否,1为存在,0不存在,这样复杂度为2^16*n(通过剪枝实际达不到这么大),可以接受。因此有两种方法解本题,(1),dfs,枚举D的k-组合。(2),通过二进制枚举D的k-组合。用dfs,最后程序跑得时间是32ms,二进制枚举跑得时间是285ms,如此大的差距,原因就是二进制把所有组合都枚举完了,其中包含很多冗余状态,说白了就是大爆力。

DFS版(32ms):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#define MAXN 1111
using namespace std;
int cow[MAXN],vis[MAXN],N,D,K,ans;
void dfs(int idx,int cnt,int sum){
    if(cnt == K){
        int num = 0;
        for(int i = 0;i < N;i ++)
            if(cow[i] == (cow[i] & sum)) num++;
        ans = max(ans,num);
        return;
    }
    for(int i = idx;i < D;i ++){
        if(!vis[i]){
            vis[i] = 1;
            dfs(i+1,cnt+1,sum|(1 << i));
            vis[i] = 0;
        }
    }
}
int main(){
    int tmp,kind;
//    freopen("in.c","r",stdin);
    while(~scanf("%d%d%d",&N,&D,&K)){
        memset(cow,0,sizeof(cow));
        memset(vis,0,sizeof(vis));
        for(int i = 0;i < N;i ++){
            scanf("%d",&tmp);
            for(int j = 0;j < tmp;j ++){
                scanf("%d",&kind);
                cow[i] |= (1 << (kind-1));
            }
        }
        ans = 0;
        dfs(0,0,0);
        printf("%d\n",ans);
    }
    return 0;
}

2.二进制枚举版(285ms):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#define MAXN 1111
using namespace std;
int cow[MAXN];
int count_digit(int n){
    int cnt = 0;
    for(int  i = 0;i < 32;i ++)
        if(n & (1 << i)) cnt ++;
    return cnt;
}
int main(){
    int n,m,k,tmp,kind;
    //freopen("in.c","r",stdin);
    while(~scanf("%d%d%d",&n,&m,&k)){
        memset(cow,0,sizeof(cow));
        for(int i = 0;i < n;i ++){
            scanf("%d",&tmp);
            for(int j = 0;j < tmp;j ++){
                scanf("%d",&kind);
                cow[i] |= (1 << (kind-1));
            }
        }
        int ans = 0;
        for(int i = 0;i < (1 << m);i ++){
            int sum = 0,cnt = 0;
            if(count_digit(i) > k) continue;
            for(int j = 0;j < n;j ++)
                if((cow[j] | i) == i) cnt++;
            ans = max(ans,cnt);
        }
        printf("%d\n",ans);
    }
    return 0;
}


posted on 2014-04-30 18:39  wangzhili  阅读(199)  评论(0编辑  收藏  举报