算法入门经典上面有三种子集生成的算法,我发现有些算法有些需要注意的地方,写出来防止被坑。
第一种是增量构造法
#include<cstdio>
int cnt=0;
void print(int *a,int cur,int n)
{
for(int i=0;i<cur;++i)
printf("%d ",a[i]);
if(cnt)
printf("\n");
int s=cur?a[cur-1]+1:0;
for(int i=s;i<n;++i)
{
a[cur]=i;
++cnt;
print(a,cur+1,n);
}
}
int main(void)
{
int n; scanf("%d",&n);
int a[1000];
print(a,0,n);
return 0;
}
第二种是位向量法
#include<cstdio> //打印出来的不是字典序顺序
void print(int *a,int cur,int n)
{
if(cur==n)
{
for(int i=0;i<n;++i)
{
if(a[i]) printf("%d ",i);
}
printf("\n");
}
else
{
a[cur]=1; print(a,cur+1,n);
a[cur]=0; print(a,cur+1,n);
}
}
int main(void)
{
int n;scanf("%d",&n);
int a[100];
print(a,0,n);
return 0;
}
第三种是二进制法
#include<cstdio>
void print(int n,int s)
{
for(int i=0;i<n;++i)
{
if(s&(1<<i)) printf("%d ",i);
}
printf("\n");
}
int main(void)
{
int n; scanf("%d",&n);
for(int i=1;i<(1<<n);++i) //注意一旦n过大,会溢出
print(n,i);
return 0;
}
第三种方法的缺点是一旦n超过31,便会溢出,优点是代码量少。
第二种方法的缺点是输出的顺序不是字典序,而且速度没第一种快,优点就是能用。
第一种方法速度快,而且是字典序,只要你数组能开那么大,n就能多大。强烈推荐使用第一种方法。
如有不当之处欢迎指出!