状态压缩 DP 学习笔记

1.集合的二进制表示

对于一个全集 U={a1,a2,a3...an} 的任意一个子集 AU ,我们可以用一个n位的二进制数来表示这一个集合。其中,末位第 i 位数为 0 表示 ai 不存在于该子集中,为 1 表示 ai 存在于该子集中。
例如:

全集 U={a1,a2,a3,a4,a5}
子集 A={a1,a3,a5}

那么我们可以用 (10101)2 来表示子集 A

2.集合的交/并/补集运算

对于全集 U  的任意两个子集 A B 的二进制表示分别为  a b ,有

AB=a and b
AB=a or b
UA=(not a)and U  

可以发现,集合的交/并/补集运算是符合位运算的特点的。
例如:

全集 U={a1,a2,a3,a4,a5}
子集 A={a1,a3}
子集 B={a2,a4}
AB=a or b=(00101)2or(01010)2=(01111)2
={a1,a2,a3,a4}
AB=a and b=(00101)2and(01010)2=(00000)2=
UA=(not a) =not(00101)2=(11010)2
={a2,a4,a5}

为什么要 and 一下 U 呢?因为在计算机中整形变量往往不止你需要的二进制位数,如果不 and 一下 U 则会在高位上产生很多不必要的 1

3.状态压缩 DP 

「状态压缩 DP 」指记录当前集合的状态,在集合上进行转移的DP。
在一些问题上,我们通常需要存储高维(四、五维以上),而且状态的范围很低(一般为存在和不存在两种),此时开高维数组的常数会呈几何倍数增加,这时我们就要用「状态压缩」来把多层状态压成一个整数。压缩状态的方式有很多,我们常用的就是「以集合的形式存储状态」。
「状态压缩DP」一般用于解决无已知多项式算法的NP完全问题(如旅行商问题)。由于需要枚举集合,所以它的复杂度是指数级别的,一般为 O(2n) 及其倍数或乘方。尽管如此,一般搜索算法动辄 O(N!) 的复杂度比「状态压缩 DP 」高到不知道哪里去了。

4.一些例题

正在施工中

你可能感兴趣的:(学习笔记)