您的位置:首页 > 其它

HDU 3006 The Number of set(位运算 状态压缩)

2013-08-26 19:11 465 查看
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3006

题目大意:给定n个集合,每个集合都是由大于等于1小于等于m的数字组成,m最大为14。由给出的集合可以组成多少个不同的集合。

输入描述:第一行为n,m,接下来n行,每行包含k+1个数字,第一个为k,表示该集合的元素个数,接下来k行表示集合元素。

[align=left]Sample Input[/align]

4 4
1 1
1 2
1 3
1 4
2 4
3 1 2 3
4 1 2 3 4

[align=left]Sample Output[/align]

15
2

分析:以为m的规模很小,可以用二进制表示集合。借助位运算的或( | )来达到集合合并的目的。
   比如一个集合中有两个元素 1 3 那就用5 (101)表示这个集合

  比如一个集合(1 4 )和一个集合(1 2 3)进行合并 那就是 (9)1001 | 111(7)=1111 就是15

代码如下:

# include<stdio.h>
# include<string.h>
int n,m,k;
int dp[1<<15];
int main(){
int i;
while(scanf("%d%d",&n,&m)!=EOF){
memset(dp,0,sizeof(dp));
while(n--){
scanf("%d",&k);
int set = 0;
int temp;
for(i=1;i<=k;i++){    //得到这个集合的二进制表示
scanf("%d",&temp);
set = set|(1<<(temp-1));
}

dp[set] = 1;
for(i=0; i<(1<<m); i++)    //将新的集合与以往得到的集合合并
if(dp[i])
dp[i|set] = 1;
}
int ans = 0;
for(i=0; i<(1<<m); i++)    //判断可以组成集合的个数
if(dp[i])
ans++;
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: