位运算与子集

很多时候,我们需要求一个集合子集,对于求子集,对于集合元素要么存在于子集中,要么不存在,

因此可以抽象用1位二进制数来表示,当该值为0,表示这个元素不在该集合中,反之则存在。

比如{a,b,c,d}, 求该集合子集,可以退化成4位二进制数_ _ _ _的排列问题, 总共排列2*2*2*2=16.

位操作1<<1=0b10, 1<<2=0b100,1<<3=0b1000,1<<4=0b10000=16,为所有子集个数,

因此若一个集合有n个元素,则子集个数为1<<n个,生成所有子集代码如下:

void bo()
{
  for(int i = 0; i < 1<<(size); i++)
  {
    for(int j = 0; j < size;j++)
    {
      sa[i][j] = i&(1<<j)&&1;  //
      cout<<sa[i][j]<<" ";
    }
    cout<<endl;
  }
}

下面是一个利用位操作,求子集的例子:

#include <iostream>

using namespace std;

#define MAX 100

int size = 0;
int sa[MAX*MAX][MAX]={0};
char ca[MAX];

void genca();
void bo();
void subset();
int main(void)
{
  cout<<"size:";
  cin>>size;
  genca();
  bo();
  subset();
  return 0;
}

void bo()
{
  for(int i = 0; i < 1<<(size); i++)
  {
    for(int j = 0; j < size;j++)
    {
      sa[i][j] = i&(1<<j)&&1;
      cout<<sa[i][j]<<" ";
    }
    cout<<endl;
  }
}

void genca()
{
  for(int i=0;i<size;i++)
    ca[i]='a'+i;
}

void subset()
{
  for(int i=0;i<1<<size;i++)
    {
	for(int j=0;j<size;j++)
	  if(sa[i][j])
	    cout<<ca[j]<< " ";
	cout<<endl;
    }

}

输出的结果如下:

 ./bo
size:3
0 0 0 
1 0 0 
0 1 0 
1 1 0 
0 0 1 
1 0 1 
0 1 1 
1 1 1 

a 
b 
a b 
c 
a c 
b c 
a b c 

点赞