对于给定的n,生成集合{1,2……n - 1}的子集
简单枚举有三种办法
1,增量构造法
一次选出一个元素放到集合中,每一次递归都需要输出集合,因为是子集
#include<cstdio>
int A[1000000];
void print_subset(int n, int cur){
for(int i = 0; i < cur; i++) printf("%d ", A[i]);
putchar('\n');
for(int i = cur ? A[cur - 1] + 1 : 0; i < n; i++){
A[cur] = i;
print_subset(n, cur + 1);
}
}
int main(void)
{
int n; scanf("%d", &n);
print_subset(n, 0);
return 0;
}
2,位向量法
对于每一个集合的位置,都用一个bool元素代表是否在集合中,因此是到n = cur的时候再输出集合
#include<cstdio>
bool B[1000000];
void print_subset(int n, int cur){
if(cur == n){
for(int i = 0; i < n; i++)
if(B[i]) printf("%d ", i);
putchar('\n');
}
else{
B[cur] = false;
print_subset(n, cur + 1);
B[cur] = true;
print_subset(n, cur + 1);
}
}
int main(void)
{
int n; scanf("%d", &n);
print_subset(n, 0);
return 0;
}
3,二进制法
和位向量法差不多,用一个标准表示这个元素是否存在,然后进行枚举,不过这里用的是二进制
#include<cstdio>
void print_subset(int n, int s){
for(int i = 0; i < n; i++)
if(s & (1 << i)) printf("%d ", i);
putchar('\n');
}
int main(void)
{
int n; scanf("%d", &n);
for(int i = 0; i < (1 << n); i++)
print_subset(n, i);
return 0;
}