子集的生成—二进制枚举
Posted wizarderror
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了子集的生成—二进制枚举相关的知识,希望对你有一定的参考价值。
有这样的一个问题:
给定一个集合,让你输出所有的子集。
这时候二进制就派上了用场~
我们用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]);
以上是关于子集的生成—二进制枚举的主要内容,如果未能解决你的问题,请参考以下文章