浅谈状态压缩dp

浅谈状态压缩dp

一、概述
1.1 状态压缩:

状态压缩指对于当前的状态,压缩成为一个二进制序列,转换为十进制存在一个整形变量中。那么显而易见的,状态压缩只能在对状态中只有 0 , 1 0,1 0,1 两种的问题起作用,比如棋盘中某个位置“有”或“没有”棋子。

1.2 状态压缩dp

状压DP,顾名思义,就是使用状态压缩的动态规划。

通过存储之前的状态,再由状态及状态对应的值推演出状态转移方程最终得到最优解。

1.3 位运算

(记得不知道运算符优先级时打括号就行)

  • 按位与&(有0为0,其实就是且)
  • 按位或|(有1为1,其实就是或)
  • 按位取反~(注意负数补码的符号,最前面的第一位是1)
  • 异或^(相同为0,不同为1)
  • 左移<<
  • 右移>>
二、例题

Luogu P1879 [USACO06NOV]Corn Fields G

观察题目,首先题目给出了选取的条件,如样例:

2 3
1 1 1
0 1 0

我们可以把这个图每一行看做一个状态集合。

所以第一行可以压成 ( 111 ) 2 = 7 (111)_2=7 (111)2=7 ,第二行可以压成 ( 10 ) 2 = 3 (10)_2=3 (10)2=3 ,注意我是从左向右从低位到高位,这样在输入的时候就可以 O ( 1 ) O(1) O(1) 处理出来,第 i i i 行存在 M a p i Map_i Mapi 中。

那么考虑建一个 d p i , S dp_{i,S} dpi,S 数组,表示第 i i i 行状态的二进制集合为 S S S 时的方案种数。

那么对于 d p i , S dp_{i,S} dpi,S ,首先判 S S S 表示的状态中是否取的全是可用土地,也就是 S S S 中有没有比 M a p i Map_i Mapi 多了 1 1 1

我选择的是对 S S S M a p i Map_i Mapi 取或,如果此结果与 M a p i Map_i Mapi 相等,那么则满足条件。(如果有多出来的 1 1 1,实际会比 M a p i Map_i Mapi 大)

然后要判这一行是否有取相邻的一,我则是将 S S S 左移一位的结果与 S S S 取与,那么如果相邻位上取了的话结果会大于 0 0 0,没取的话等于 0 0 0

例如 101 101 101 这个状态,左移一位后为 1010 1010 1010 ,显然的,对齐以后没有一位上两个数都为 1 1 1,所以取与结果为 0 0 0

对于 110 110 110 这个状态,左移一位后为 1100 1100 1100,显然的,第三位上取与后为 1 1 1 ,所以结果为 8 ≠ 0 8 \neq 0 8=0

然后观察后发现,对于第 i i i 行,只需要判第上一行有没有取同位1即可,所以与上一位取得集合取与,如果为 0 0 0 满足要求

把上述的总结成函数 f ( S 1 , S 2 ) f(S_1,S_2) f(S1,S2) ,表示判 S 1 S_1 S1 对 上一行取 S 2 S_2 S2 的情况的合法情况,如果合法返回 1 1 1, 不合法返回 0 0 0

函数 G ( x , S ) G(x,S) G(x,S) 表示第 x x x 行取 S S S 的合法情况, 如果合法返回 1 1 1, 不合法返回 0 0 0。(只是方便书写)

所以 :
d p i , S = { 0 G ( i , S ) = 0 ∑ k = 0 k = 2 n − 1 f ( i , S ) × d p i − 1 , k G ( i , S ) = 1 dp_{i,S}=\begin{cases}0&G(i,S)=0\\\sum_{k=0}^{k=2^n-1}f(i,S)\times dp_{i-1,k}&G(i,S)=1\end{cases} dpi,S={0k=0k=2n1f(i,S)×dpi1,kG(i,S)=0G(i,S)=1
对于每一行,先跑出前面,然后再把本行所以状态跑完就行了。

最后答案为 ∑ k = 0 k = 2 n − 1 d p m , k \sum_{k=0}^{k=2^n-1}dp_{m,k} k=0k=2n1dpm,k

今晚把代码贴上去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值