子集的生成—二进制枚举

有这样的一个问题:

给定一个集合,让你输出所有的子集。

这时候二进制就派上了用场~

我们用0,1来表示当前位是否被保留,值为1则保留,为0则舍弃 ,如下图所示:

那么对于一个有n个数的集合来讲,每一位有取和不取两种状态,一共就有2n种状态,我们可以从0一直枚举到2n来表示所有子集的状态。

但是现在问题又来了,对与我们枚举的数,你怎么知道哪一位是0,哪一位是1?

这个时候就要用到位运算的知识了,对于一个数S(子集的状态)我们拿它和0~n每一位i进行S&(1<<i)这样的运算就能得到对于的位是否为1(&运算符的特点是只有当对应位都为1时,运算结果才为1)

举个栗子,S = 13,对于的二进制码为1101

1101 & 0001得到第一位为1

1101 & 0010得到第二位为0

1101 & 0010得到第三位为1

1101 & 1000得到第四位为1

这样就得到我们取集合中的1,3,4位

实现代码:

for(int i = 0; i < (1<<n); i++) //二进制枚举每一个状态
    for(int j = 0; j < n; j++) //枚举该状态下二进制的每一位数值
        if(i&(1<<j)) //当前位是否为1
            printf("%d ", a[j]);
posted @ 2019-08-16 17:40  sparkyen  阅读(651)  评论(0编辑  收藏  举报