比萨(nhoi2009pj3)
Time
Limit:1000MS Memory Limit:65536K
Total Submit:3 Accepted:3
Description
NH的最大比萨店为即将来临的节日准备了 T 种不同加味的原料,但考虑到NH人的口味和其它一些因素,原料的使用有 N 种限制。
T种不同原料的编号为1..T。一个限制如“5 3”即表示5号和3号加味原料不能同时使用。如此,此时使用三种原料3,5,6的比萨是不允许的。
现在请你帮忙计算在上面条件下,最多可以制作多少不同的比萨(包括不添加任何加味原料的)。
Input
第一行:两个整数:T 和 N。
下面有N行:每行表示一种限制。每行的第一个整数 Z(1≦Z≦ T)表示这行后面有Z个表示原料编号的整数,这些原料不能同时出现在一个比萨中。
Output
只一行,一个整数表示在上面的限制下最多可以制成多少种不同比萨。
Sample Input
6 5
1 1
2 4 2
3 3 2 6
1 5
3 3 4 6
Sample Output
10
答案说明:
无加料;2;
2和3;2和6;
3;3和4;
3和6;4;
4和6;6。
Hint
1≦T≦20
1≦N≦52
反思:
这道题不难,一个两重循环就搞定了,依个枚举,再用位运算来判断。最主要要注意的是判断时位运算的优先级问题,尽量加一些括号,不然位运算的优先级问题很烦人……
#include <iostream>
#include <cstdio>
using namespace std;
int cantput[51];
void turn_to_two_base_and_print(int n){
string s;
while(n!=0){
s.push_back((char)(n&1)+'0');
n>>=1;
}
cout << s << endl;
}
int main(){
freopen("pizza.in","r",stdin);
freopen("pizza.out","w",stdout);
int n,t;
scanf("%d %d",&t,&n);
int z,tmp;
for (int i=0;i<n;++i){
scanf("%d",&z);
cantput[i]=0;
for (int j=0;j<z;++j){
scanf("%d",&tmp);
cantput[i]+=(1<<(tmp-1));
}
}
/*
for (int i=0;i<n;++i){
turn_to_two_base_and_print(cantput[i]);
}
*/
bool canUse;
unsigned int ans=0;
for (int i=0;i<(1<<(t));++i){
canUse=true;
for (int j=0;j<n;++j){
if ((i&cantput[j])==cantput[j]){
canUse=false;
break;
}
}
if (canUse){
++ans;
}
}
printf("%u\n",ans);
}