聚餐

聚餐

Description

为了庆祝机考,ACM班的m个同学决定去聚餐。

到了餐厅以后,他们发现一共有n个可供选择的菜(编号为1,2,⋯, n),所以每个同学都向负责点菜的班长大人提出了一些要求。比如,一个同学表示,他一定要吃辣;另一个同学表示,他不能看到维生素C。当然,要满足所有人的所有要求是很难做到的,因此只要有至少一个要求被满足,这个同学就会开心的去吃饭。

现在问题来了:班长是否能选择一些菜,使得所有人都能开心?

Input

第一行是一个正整数t (1<=t<=5),表示数据组数。每一组数据之间有一行空行。

对于一组数据,第一行有两个正整数n (1<=n<=20), m (1<=m<=60),用空格隔开。接下来有m行,每行有不超过n个整数,中间用空格隔开。

对于第i行的某个整数,如果是正整数k,表示同学i一定要吃编号为k的菜;如果是负整数-k,表示同学i不能忍受餐桌上有编号为k的菜。

Output

如果能够使所有人都开心,则输出”Bingo!”,否则输出”Sigh…”。

Hint

注意到数据范围很小我们可以直接 220 2 20 爆搜,但是我们发现加上验证的复杂度我们的总复杂度是 60205220 60 ∗ 20 ∗ 5 ∗ 2 20 ,于是就愉快TLE了
预处理 预处理运用了2进制思想(正如状压dp中我们用的方法),我们对第 k k 道菜用一个long long变量(设为 ak a k )记录下它的属性,可以满足第 i i 人则将 ak a k 的二进制的第 i i 位赋值为1,否则为0.
则如果存在一些菜,它们的a值全部或运算之后每一位都是1那么这些菜可以满足所有人
这题还有一点,就是输入很麻烦,可以用sscanf解决,或者读入优化.

Code

错误代码

#include
#include
#include
#include
#include
#include
#define siz 100
using namespace std;
template <class T>
bool read(T &re) {
    re=0;
    int flag=1;
    char c=getchar();
    if(c=='-') flag=-1,c=getchar();
    while(c>='0'&&c<='9') re=(re<<1)+(re<<3)+c-'0',c=getchar();
    re*=flag;
    if(c=='\n') return 0;
    return 1;
}
int t,n,m,ai,frag;
long long a[siz],b[siz];
void search(int p,long long data) {
    if(frag||p==n+1) return;
    if(data==((1<<(m+1))-2)) { frag=1; puts("Bingo!"); return ;}
    search(p+1,data|a[p]);
    search(p+1,data|b[p]);
}
int main() {

    read(t); 
    getchar();
    while(t--) {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        read(n),read(m);
        for(int i=1;i<=m;++i) 
          while(1) {
            frag=read(ai);
            if(ai>0) a[ai]|=(1<else b[-ai]|=(1<if(!frag) break; 
          }
        frag=0;
        search(1,0);
        if(!frag) puts("Sigh..."); 
        if(t) getchar();
    }
    return 0;
}

后来询问了学姐发现了错误之处:
1.搜索中,如果p==n+1时恰好满足条件就会直接return导致错误,实际上判断的正确顺序应该要是:if(frag),if(data==((1<<(m+1))-2)),if(p==n+1),逻辑上需要加强
2.<<运算默认是int范围,若是要移到long long范围内要使用ll<<
还是有一些小知识不知道呢,要继续加油

#include
#include
#include
#include
#include
#include
#define siz 100
using namespace std;
template <class T>
bool read(T &re) {
    re=0;
    int flag=1;
    char c=getchar();
    if(c=='-') flag=-1,c=getchar();
    while(c>='0'&&c<='9') re=re*10+c-'0',c=getchar();
    re*=flag;
    if(c=='\n') return 0;
    return 1;
}
int t,n,m,ai,frag;
long long a[siz],b[siz];
void search(int p,long long data) {
    if(frag) return ;
    if(data==((1ll<<(m+1))-2)) { frag=1; puts("Bingo!"); return ;}
    if(p==n+1) return;
    search(p+1,data|a[p]);
    search(p+1,data|b[p]);
}
int main() {

    read(t); 
    getchar();
    while(t--) {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        read(n),read(m);
        for(int i=1;i<=m;++i) 
          while(1) {
            frag=read(ai);
            if(ai>0) a[ai]|=(1ll<else b[-ai]|=(1ll<if(!frag) break; 
          }
        frag=0;
        search(1,0);
        if(!frag) puts("Sigh..."); 
        if(t) getchar();
    }
    return 0;
}

你可能感兴趣的:(好题收集)