状压DP

到博客字体就变小了,怎么会是呢

定义及相关原理

状态压缩动态规划,就是俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。

很多棋盘问题都运用到了状压,同时,状压也很经常和 BFSDP 连用。

状压dp其实就是将状态压缩成2进制来保存,其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划。

我们最多只需要 \(2^{n + 1}- 1\) 的十进制数就好(二进制形式是n个1),用十进制表示二进制的数,枚举了全部的状态,DP起来复杂度岂很大。状压其实是一种很暴力的算法,他需要遍历每个状态,所以将会出现 \(2^n\) 的情况数量,不过这并不代表这种方法不适用:一些题目可以依照题意,排除不合法的方案,使一行总方案数大大减少从而减少枚举。


位运算相关:

位运算(这篇博客很详细)

  1. 位与:‘ & ’ 符号,x & y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如 3 ( 11 ) & 2 ( 10 ) = 2 ( 10 )。

  2. 位或:‘ | ’符号,x | y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如 3 ( 11 ) | 2 ( 10 ) = 3 ( 11 )。

  3. 异或:‘ ^ ’符号,x ^ y,会将两个十进制数在二进制下进行异或运算(不同为1,其余为0)然后返回其十进制下的值。例如 3 ( 11 ) ^ 2 ( 10 ) = 1 ( 01 )。

  4. 位取反:‘ ~ ’符号,~ x,按位取反。例如 ~101 = 010。

  5. 左右移:‘ << ’符号,左移操作,x << 2,将x在二进制下的每一位向左移动两位,最右边用0填充,x << 2相当于让x乘以4。 ’ >> ’符号,是右移操作,x > > 1 相当于给 x / 2,去掉 x 二进制下的最右一位。

Some Skills

  1. 判断一个数字 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。

  2. 将一个数字 x 二进制下第i位更改成1。

    方法:x = x | ( 1 << ( i−1 ) ) 证明方法与1类似。

    证明:(1<<(i-1))构造出了只有第 i 位为 1,其余全为 0 的数。与 x 取或,只有 x 在第 i 位会 “ 1 | 0 = 1 ”,从而第 i 位变成 1 。

  3. 将一个数字 x 二进制下第 i 位更改成 0。

    方法:x = x & ~ ( 1 << ( i−1 ) )。

    证明:对 (1<<(i-1)) 取反,可以得到类似011111...的数,与 x 取 & ,则除了第 i 位外都还是原数。第 i 位会" 0 & 1 = 0 "。

  4. 把一个数字二进制下最靠右的第一个 1 去掉。

    方法:x = x & ( x − 1 )。

    证明:对 x-1,则最后一个 1 \(\Rightarrow\) 0,再与 x 取 & ,最后一个 1 以外都为原数不变。只有变化的地方 “ 0 & 1 = 0 ”。

posted @ 2023-06-19 19:41  XYini  阅读(4)  评论(0)    收藏  举报