知识点-子集生成
解决问题
生成一个集合的所有子集
复杂度
O ( 2 n ) O(2^n) O(2n)
例题
hdu1584
代码
一、增量构造法
按递增顺序构造子集,防止子集重复
如下,A数组用来存储下标
#include<stdio.h>
int A[100];
int T[100];
void print_subset(int n,int *A,int cur)
{
for(int i=0;i<cur;i++)
printf("%d ",T[A[i]]);//输出子集 当前的集合
printf("\n");
int s=cur?A[cur-1]+1:0;//确定当前最小的可能值 如果这里不是 这里特殊的就是cur==0时 其他的就是选比前一个大1的
for(int i=s;i<n;i++)
{
A[cur]=i;//将i加入当前的集合
print_subset(n,A,cur+1);// 递归构造子集
}
}
int main()
{
int n;scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&T[i]);
print_subset(n,A,0);
}
二、位向量法
用B数组存储每一位取不取
#include<stdio.h>
int B[100];
int T[100];
void print_subset(int n,int *B,int cur)
{
if(cur==n)
{
for(int i=0;i<cur;i++)
if(B[i])printf("%d ",T[i]);
printf("\n");
return ;
}
B[cur]=1;
print_subset(n,B,cur+1);//选
B[cur]=0;
print_subset(n,B,cur+1);//不选
}
int main()
{
int n;scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&T[i]);
print_subset(n,B,0);
}
三、二进制法
用二进制的每一位代表一个数取不取
实现简洁
#include<stdio.h>
int B[100];
int T[100];
void print_subset(int n,int s)
{
for(int i=0;i<n;i++)
if(s&(1<<i))printf("%d ",T[i]);
printf("%n");
}
int main()
{
int n;scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&T[i]);
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
}