Codeforces Round #438 C.Qualification Rounds(状态压缩再枚举状态)

题目链接:Qualification Rounds
题意:给出n,k。n个题目,k个人,k个人中每个人做过那个题目的关系也给出来。现在问能不能在这n个题目中选出一定数量的题组成一个题集,使得k个人中的任何一个人在这个题集中做过的题不超过题数的一半。

思路:刚开始想到,如果有一题k个人都做过,那么这一题绝对不选,如果有一题k个人都没做过,直接可以输出“YES”,问题在于那些完成的人数>0且< k的题里面,接着就想到了如果选两题就能输出“YES”的话,那么这两题一定没有交集;选3题输出“YES”的话,那么3题中的两题必须没有交集,否则意味着有一个人做过3题中的两题,大于1/2了。选四题,选五题…要输出“YES”,至少都要求存在两个题做过的人没有交集。

所以,只需要判断存不存在两个题,使得两个题做过的人没有交集。由于题目数n高达1e5,n^2遍历铁定超时,而k最大只有4,所以这题关键在于状态压缩再枚举状态。存状态,状态最多只有16种,0000~1111,枚举状态,如果状态存在且作与运算结果为0,证明两个状态没有交集,输出“YES”。

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
const double eps = 1e-6;
const double Pi = acos(-1.0);
const int INF=0x3f3f3f3f;
const int MOD = 1e9+7;
const int maxn = 1e5+10;
int mat[maxn][4],num[4];
int main(){
    int n,k;
    int state,x;
    int vis[20];
    while(~scanf("%d%d",&n,&k)){
        mem(vis,0);
        for(int i = 0; i < n; i++){
            state = 0;
            for(int j = 0; j < k; j++){
                scanf("%d",&x);
                state += (1 << j) * x;
            }
            vis[state] = 1;
        }
        bool flag = false;
        for(int i = 0; i < 16; i++){
            for(int j = 0; j < 16; j++){
                if(vis[i] && vis[j] && (i & j) == 0){
                    flag = true;
                }
            }
        }
        if(flag) puts("YES");
        else puts("NO");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值