子集生成和组合问题

包含n个元素的集合的子集和二进制数的对应关系:

每个子集对应一个二进制数,这个二进制数中的每个1都对应着这个子集中的每个元素,而且子集中的元素是没有顺序的。

打印n个数中任意m个数的组合,对照子集生成的二进制方法,已经知道一个子集对应一个二进制数,那么一个有k个元素的子集,它对应的二进制数中有k个1,所以将问题转化为查找1的个数为k的二进制数。

如何判断二进制数中1的个数为k?

1.对这个n位二进制数逐位检查,共需要检查n次。

2.另一种方法可以直接定位二进制数中1的位置,跳过中间的0.操作:kk=kk&(kk-1),其功能是消除kk的二进制数的最后一个1,连续进行这个操作,每次消除一个1,直到全部消除为止,操作次数就是1的个数。

此操作可以计算出二进制数中1的个数,具体步骤如下:

(1)用kk=kk&(kk-1)消除kk的最后一个1.

(2)num++;

(3)继续上述操作,直到kk=0;

#include<bits/stdc++.h>
 using namespace std;
 void print_set(int n,int k){
     for(int i=0;i<(1<<n);i++){   //按位 
         int num=0,kk=i;
         while(kk){
             kk=kk&(kk-1);   //清除kk中最后一个1; 
             num++;          //统计1的个数; 
         }
         if(num==k){       //符合条件 
             for(int j=0;j<n;j++){
                 if(i&(1<<j))
                 cout<<j<<" ";
                 cout<<endl;
             }
         }
     }
     } 
     int main(){
         int n,k;    //n:元素的总数量   k:个数为k的子集 
         cin>>n>>k;
         print_set(n,k);
     }
原文地址:https://www.cnblogs.com/hrlsm/p/13206983.html