为了庆祝机考,ACM班的m个同学决定去聚餐。
到了餐厅以后,他们发现一共有n个可供选择的菜(编号为1,2,⋯, n),所以每个同学都向负责点菜的班长大人提出了一些要求。比如,一个同学表示,他一定要吃辣;另一个同学表示,他不能看到维生素C。当然,要满足所有人的所有要求是很难做到的,因此只要有至少一个要求被满足,这个同学就会开心的去吃饭。
现在问题来了:班长是否能选择一些菜,使得所有人都能开心?
第一行是一个正整数t (1<=t<=5),表示数据组数。每一组数据之间有一行空行。
对于一组数据,第一行有两个正整数n (1<=n<=20), m (1<=m<=60),用空格隔开。接下来有m行,每行有不超过n个整数,中间用空格隔开。
对于第i行的某个整数,如果是正整数k,表示同学i一定要吃编号为k的菜;如果是负整数-k,表示同学i不能忍受餐桌上有编号为k的菜。
如果能够使所有人都开心,则输出”Bingo!”,否则输出”Sigh…”。
注意到数据范围很小我们可以直接 220 2 20 爆搜,但是我们发现加上验证的复杂度我们的总复杂度是 60∗20∗5∗220 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解决,或者读入优化.
错误代码
#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;
}