定义
先给出子集的定义:子集是一个数学概念:如果集合A的任意一个元素都是集合B的元素,那么集合A称为集合B的子集。
用途
在写程序的时候,有时候我们可能需要暴力枚举出所有的情况,这时可以考虑通过二进制来枚举子集来尝试解决问题。
解释
假设我们现在有5个小球,上面分别标号了0,1,2,3,4
代表这些小球的权值,现在要像你求出这些小球的权值可以组成的所有情况。
我们用二进制的思维来考虑这个问题,因为有5个小球,所以我们用5个比特位来分别标记小球存在还是不存在,对于这样一种情况,比如我们现在要选择3个小球,分别是0,3,4
号小球,那么我们用二进制1
表是当前的小球存在,用0
表示当前小球不存在
二进制下标 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|
二进制 | 1 | 1 | 0 | 0 | 1 |
小球状态 | 存在 | 存在 | 不存在 | 不存在 | 存在 |
我们可以用5个比特位来表示这种情况,如果小球全部选择的话那么二进制表示就是11111
,二进制的11111
转化为十进制数字就是31
,这个数字正好就是
25−1
2
5
−
1
,那么我们可以用从
0
0
~这些数表示完所有的选取状态(因为这个范围内的二进制数情况正好包括了这些选取状况).
代码实现
用代码实现非常简单,具体看注释
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n=5;//5个小球
for(int i=0; i<(1<<n); i++) //从0~2^5-1个状态
{
for(int j=0; j<n; j++) //遍历二进制的每一位
{
if(i&(1<<j))//判断二进制第j位是否存在
{
printf("%d ",j);//如果存在输出第j个元素
}
}
printf("\n");
}
return 0;
}
例题
例题可以做一下HDU-5616
。