状压DP
到博客字体就变小了,怎么会是呢
定义及相关原理
状态压缩动态规划,就是俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。
很多棋盘问题都运用到了状压,同时,状压也很经常和 BFS 及 DP 连用。
状压dp其实就是将状态压缩成2进制来保存,其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划。
我们最多只需要 \(2^{n + 1}- 1\) 的十进制数就好(二进制形式是n个1),用十进制表示二进制的数,枚举了全部的状态,DP起来复杂度岂很大。状压其实是一种很暴力的算法,他需要遍历每个状态,所以将会出现 \(2^n\) 的情况数量,不过这并不代表这种方法不适用:一些题目可以依照题意,排除不合法的方案,使一行的总方案数大大减少从而减少枚举。
位运算相关:
位运算(这篇博客很详细)
-
位与:‘ & ’ 符号,x & y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如 3 ( 11 ) & 2 ( 10 ) = 2 ( 10 )。
-
位或:‘ | ’符号,x | y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如 3 ( 11 ) | 2 ( 10 ) = 3 ( 11 )。
-
异或:‘ ^ ’符号,x ^ y,会将两个十进制数在二进制下进行异或运算(不同为1,其余为0)然后返回其十进制下的值。例如 3 ( 11 ) ^ 2 ( 10 ) = 1 ( 01 )。
-
位取反:‘ ~ ’符号,~ x,按位取反。例如 ~101 = 010。
-
左右移:‘ << ’符号,左移操作,x << 2,将x在二进制下的每一位向左移动两位,最右边用0填充,x << 2相当于让x乘以4。 ’ >> ’符号,是右移操作,x > > 1 相当于给 x / 2,去掉 x 二进制下的最右一位。
Some Skills
-
判断一个数字 x 二进制下第i位是不是等于 1 。(最低第 1 位)
方法:
if(((1<<(i−1))&x)>0)将1左移 i-1 位,相当于制造了一个只有第 i 位上是1,其他位上都是 0 的二进制数。然后与 x 做与运算,如果结果 > 0, 说明 x 第 i 位上是 1 ,反之则是 0 。证明:
(1<<(i-1))构造出了只有第 i 位为 1 ,其余全为 0 的数。与 x 取余,只有 x 在第 i 位上有数时,结果 > 0。 -
将一个数字 x 二进制下第i位更改成1。
方法:x = x | ( 1 << ( i−1 ) ) 证明方法与1类似。
证明:
(1<<(i-1))构造出了只有第 i 位为 1,其余全为 0 的数。与 x 取或,只有 x 在第 i 位会 “ 1 | 0 = 1 ”,从而第 i 位变成 1 。 -
将一个数字 x 二进制下第 i 位更改成 0。
方法:x = x & ~ ( 1 << ( i−1 ) )。
证明:对
(1<<(i-1))取反,可以得到类似011111...的数,与 x 取 & ,则除了第 i 位外都还是原数。第 i 位会" 0 & 1 = 0 "。 -
把一个数字二进制下最靠右的第一个 1 去掉。
方法:x = x & ( x − 1 )。
证明:对 x-1,则最后一个 1 \(\Rightarrow\) 0,再与 x 取 & ,最后一个 1 以外都为原数不变。只有变化的地方 “ 0 & 1 = 0 ”。

浙公网安备 33010602011771号