位压缩
位压缩是通过k进制的一位来表示数据中一个状态的一种存储压缩方式,它可以在常数级上优化一个算法,例如我们通常所说的状态压缩动态规划,就是用二进制中的一位来表示所求问题中的一个中间状态,当然这样描述还是比较抽象的。
换个例子,对于一个图来说,如果我们只关心两个边之间的相邻关系,那么我们实际上可以用一个二进制位来表示,用0,表示两点之间没有边,而用1表示两点之间存在一条边,那么我们就可以用一个长的二进制串来表示某一点与其他所有点的相邻关系,而二进制串的长度就是所有顶点的个数。这样就比我们直接使用二维数组的空间时间复杂度降低了一个常数级别(32倍),而C++中有一个数据结构就是bitset<32>,它可以用来初始化一个位数为32的二进制串,实际上bitset的长度是比较灵活的,我们可以将32换成其他的任意常数,用来表示长度位该常数的二进制串,这样上面用二维数组描述的图结构就可以换成 bitset<n> mat[n]来表示,注意n一定是一个常数,而不能是一个变量。
通过使用位压缩,我们可以将对于基本数据类型的操作转变成对位的运算,这样我们只需要掌握bitset的常用操作即可。
bitset常用操作
bitset存储二进制数位。
bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一。
bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,表达式foo[3]访问了它的第4个元素,就像数组一样。
bitset有一个特性:整数类型和布尔数组都能转化成bitset。
bitset的大小在编译时就需要确定。如果你想要不确定长度的bitset,请使用(奇葩的)vector
bitset常用函数
1. 位运算都可以用: 与、或、非、异或,左移,右移
2. foo&foo2
3. foo|foo2
4. ~foo
5. foo^foo2
6. foo<<=2
7. foo>>=2
8. foo.size() 返回大小(位数)
9. foo.count() 返回1的个数
10. foo.any() 返回是否有1
11. foo.none() 返回是否没有1
12.