数论中的子集生成

子集生成

#include <iostream>
#include <cstring>
using namespace std;
int a[20];   //存放子集的集合
//n表示元素个数和最小的不可取数,cur表示当前下标,初始值为0
void print_subset1(int n,int *a,int cur)  //增量构造法,每次从可取数中取一个尽可能小的数放入子集再打印。
{
   for(int i=0;i<cur;i++)  cout<<a[i]<<",";  //输出当前集合
   cout<<endl;
   int s=cur;
   if(s>0)  s=a[cur-1]+1;  //若cur在1及其以后的位置,则s取前一个数加1的数,为的是尽可能去最小数
   else  s=0;              //后一个数必须比前一个数大,才可以保证各个子集的集合互异性
   for(int j=s;j<n;j++)   //a[cur]的所有可取值j
   {
      a[cur]=j;  //赋值
      print_subset1(n,a,cur+1);  //进行下一轮递归,扩充子集
   }
}
void print_subset2(int n,int *a,int cur)  //位向量法,枚举所有可能
{  //a数组存放的是下标i是否存在于子集中
   if(cur==n)  //当n个元素的存在与否已确定,打印子集
   {
     for(int i=0;i<=n;i++)
        if(a[i]==1)  cout<<i<<",";
     cout<<endl;
   }
   else{  //枚举所有情况
          a[cur]=1;   print_subset2(n,a,cur+1);
          a[cur]=0;   print_subset2(n,a,cur+1);
   }
}
int main()
{   int n;
    while(cin>>n&&n)
    {
      memset(a,0,sizeof(a));
      print_subset2(n,a,0);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39905917/article/details/83039114
今日推荐