1.集合的二进制表示
对于一个全集
U={a1,a2,a3...an}
的任意一个子集
A⊆U
,我们可以用一个n位的二进制数来表示这一个集合。其中,末位第
i
位数为
例如:
全集 U={a1,a2,a3,a4,a5}
子集 A={a1,a3,a5}
那么我们可以用 (10101)2 来表示子集 A 。
2.集合的交/并/补集运算
对于全集
A∩B=a and b
A∪B=a or b
∁UA=(not a)and U
可以发现,集合的交/并/补集运算是符合位运算的特点的。
例如:
全集
U={a1,a2,a3,a4,a5}
子集 A={a1,a3}
子集 B={a2,a4}
A∪B=a or b=(00101)2or(01010)2=(01111)2
={a1,a2,a3,a4}
A∩B=a and b=(00101)2and(01010)2=(00000)2=∅
∁UA=(not a) =not(00101)2=(11010)2
={a2,a4,a5}
为什么要
and
一下
U
呢?因为在计算机中整形变量往往不止你需要的二进制位数,如果不
3.状态压缩 DP
「状态压缩 DP 」指记录当前集合的状态,在集合上进行转移的DP。
在一些问题上,我们通常需要存储高维(四、五维以上),而且状态的范围很低(一般为存在和不存在两种),此时开高维数组的常数会呈几何倍数增加,这时我们就要用「状态压缩」来把多层状态压成一个整数。压缩状态的方式有很多,我们常用的就是「以集合的形式存储状态」。
「状态压缩DP」一般用于解决无已知多项式算法的NP完全问题(如旅行商问题)。由于需要枚举集合,所以它的复杂度是指数级别的,一般为
O(2n)
及其倍数或乘方。尽管如此,一般搜索算法动辄
O(N!)
的复杂度比「状态压缩 DP 」高到不知道哪里去了。
4.一些例题
正在施工中