题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3006
题目大意:给定n个集合,每个集合都是由大于等于1小于等于m的数字组成,m最大为14。由给出的集合可以组成多少个不同的集合。
输入描述:第一行为n,m,接下来n行,每行包含k+1个数字,第一个为k,表示该集合的元素个数,接下来k行表示集合元素。
Sample Input
4 4
1 1
1 2
1 3
1 4
2 4
3 1 2 3
4 1 2 3 4
Sample Output
15
2
分析:以为m的规模很小,可以用二进制表示集合。借助位运算的或( | )来达到集合合并的目的。
比如一个集合中有两个元素 1 3 那就用5 (101)表示这个集合
比如一个集合(1 4 )和一个集合(1 2 3)进行合并 那就是 (9)1001 | 111(7)=1111 就是15
代码如下:
1 # include<stdio.h> 2 # include<string.h> 3 int n,m,k; 4 int dp[1<<15]; 5 int main(){ 6 int i; 7 while(scanf("%d%d",&n,&m)!=EOF){ 8 memset(dp,0,sizeof(dp)); 9 while(n--){ 10 scanf("%d",&k); 11 int set = 0; 12 int temp; 13 for(i=1;i<=k;i++){ //得到这个集合的二进制表示 14 scanf("%d",&temp); 15 set = set|(1<<(temp-1)); 16 } 17 18 dp[set] = 1; 19 for(i=0; i<(1<<m); i++) //将新的集合与以往得到的集合合并 20 if(dp[i]) 21 dp[i|set] = 1; 22 } 23 int ans = 0; 24 for(i=0; i<(1<<m); i++) //判断可以组成集合的个数 25 if(dp[i]) 26 ans++; 27 printf("%d ",ans); 28 } 29 return 0; 30 }