/*子集生成的各种实现*/ #include <iostream> #include<algorithm> #include<queue> #include<stack> #include<cmath> #include<string.h> #include<stdio.h> #include<stdlib.h> using namespace std; #define maxn 26000 int A[maxn]; int B[maxn]; int n,sum; void print_subset(int n,int *A, int cur)//用增量法实现子集生成 { int i; for(i=0; i < cur ; i++) { printf("%d ",A[i]);//打印当前集合 if(i==0) sum++;//没有把空集列出来,共2^n-1个 } printf(" "); int s = cur ?A[cur-1]+1 : 0;//确定当前元素最小可能值 for(i=s; i<n; i++) { A[cur]=i; printf("cur = %d i = %d ",cur,i); printf("调用print_subset( %d ) ",cur+1); print_subset(n,A,cur+1);//递归构造子集 } } void print_subset1(int n,int *B,int cur)//用位向量法实现子集生成 { printf("cur = %d n = %d ",cur,n); if(cur==n) { for(int i=0; i<cur; i++) if(B[i]) printf("%d ",i);//打印当前集合 sum++;//共有2^n个 printf(" "); return ; } B[cur]=1; print_subset1(n,B,cur+1);//选第cur个元素 B[cur]=0; print_subset1(n,B,cur+1);//不选第cur个元素 } //二进制法 //当用二进制表示子集时,位运算中的按位与、或、异或对应集合的交、并、和对称差 void print_subset2(int n,int s)//打印{0,1,2,3,...,n-1}的子集S { for(int i=0; i<n; i++) if(s&(1<<i)) printf("%d ",i); printf(" s = %d",s); printf(" "); } int main() { while(~scanf("%d",&n)) { sum=0; //print_subset(n,A,0); //print_subset1(n,B,0); //printf("sum = %d ",sum); for(int i=0; i<(1<<n); i++)//枚举各子集所对应的编码0,1,2,3,...,2^n-1 print_subset2(n,i); printf("sum = %d ",1<<n); } return 0; }