The Number of set
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1301 Accepted Submission(s): 795
Problem Description
Given you n sets.All positive integers in sets are not less than 1 and
not greater than m.If use these sets to combinate the new set,how many
different new set you can get.The given sets can not be broken.
Input
There are several cases.For each case,the first line contains two
positive integer n and m(1<=n<=100,1<=m<=14).Then the
following n lines describe the n sets.These lines each contains k+1
positive integer,the first which is k,then k integers are given. The
input is end by EOF.
Output
For each case,the output contain only one integer,the number of the different sets you get.
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
Source
2009 Multi-University Training Contest 11 - Host by HRBEU
题意:n个集合,每个集合里面有t个数字,每个数字都属于 1-m(m<=14) ,问这些集合合并起来总共有多少可能性??
题解:第一次用状态压缩,,在队友的提示下虽然WA了一次,RE了两次,但是还是挺开心的。
一个集合最多也就有14个数字,我们用 二进制表示 一个集合的所有情况 比如说 某个集合包含 {1,3,11} 那我们的表示为 k = 00010000000101
然后我们每次把当前状态置为a[k] = 1;然后当碰到下一个状态t时,我们就到所有状态(FOR i 1-(1<<14))里面去找a[i]=1
然后a[i|t] = 1 最后遍历求出有多少a[i]为1即可。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define N 14 using namespace std; int a[(1<<N)+1]; ///14位,最低位存0,2的14次方保存的是 100000000000000可以存15位,所以最大用到 2^14-1 int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF){ int t,num,k; memset(a,0,sizeof(a)); for(int i=1;i<=n;i++){ scanf("%d",&t); k=0; for(int j=1;j<=t;j++){ scanf("%d",&num); k+=(1<<(num-1)); } a[k]=1; for(int j=1;j<=(1<<N);j++){ if(a[j]){ int next = k|j; a[next]=1; } } } int ans = 0; for(int i=1;i<=(1<<N);i++){ if(a[i]) ans++; } printf("%d\n",ans); } return 0; }