有关状态压缩dp

其实状态压缩dp就是一个普通的dp加一个对集合的操作,只是把这个集合“压缩”一下,所以这里简单说一下怎样表示一个集合以及对它进行操作。

首先,我们为什么要状态压缩?因为有时我们需要用东西表示一个集合。比如经典的TSP问题,它需要用到一个集合S来表示已经遍历的点(这些点用不同的数字表示),那么如何来表示集合S呢?这里我们可以利用二进制的方法:将集合中的元素对应二进制中的1,其它的为0,这样就产生了一个二进制数,这个二进制数对应着一个十进制数,所以这个十进制数就可表示这个集合。由于不同的集合对应着不同的二进制,也就有不同的十进制数,所以不用担心一个十进制数会对应着不同的集合。比如:集合{1,3,4}可表示为11010,也就是26。集合{0,3,4,8}可表示为100011001,也就是21。从左往右、从0可是标号。

然后说一下位运算。位运算是对于二进制的运算,两个十进制数间进行为运算时它会自动将两个数转化为二进制数进行运算。为运算有"&"(与运算)、"|"(或运算)、"^"(与或运算)、“~”(取反)。这些位运算的运算法则我就不说了,自己不知道可以百度下。我说下他们对集合的意义:

& :取两个集合的交

|  : 取两个集合的并

^ : 取两个集合的对称差

~ : 对一个集合取反(也就是集合s与集合~s的交集为空)

还有"<<"(左移)、">>"(右移)也是重要的运算符。


假设集合S有n个元素{0,1,...,n-1},则一些集合运算可以对应地写成如下方式。


空集∅:.......................................................................0

只含有第i个元素的集合{i}: ...........................................1<<i      (此时在二进制中只有第i个位置时1,其余为0)

含有全部n个元素的集合{0,1,...,n-1}: ...........................(1<<n)-1   (此时二进制中位置0,1,...n-1上都是1)

判断第i个元素是否属于集合S:...................................if(S>>i&1)    (就是判断第i个位置是否为1,也可以写成if(S&(1<<i)),这里">>"运算优先级比"&"高)

向集合中加入第i个元素S∪{i}:...................................S|1<<i        (保证集合S中的第i位一定是1,"<<“运算优先级比"|"高)

向集合中去除第i个元素S\{i}:......................................S&~(1<<i)   (保证集合S中的第i位一定是0)

集合S和T的并集S∪T:...............................................S|T

集合S和T的交集S∩T:................................................S&T


x&(-x) : 将x最低位的1独立出来后的值。

x&(x-1) : 将x的最低位的1变为0后的值。

x|(x+1) : 将x的最低位的0变为1后的值。


相关题目:

① 炮兵阵地(我的入门题,需要dp知识):http://poj.org/problem?id=1185

② 搜索+状态压缩 :http://acm.hdu.edu.cn/showproblem.php?pid=5025

③ TSP问题 :http://codeforces.com/problemset/problem/580/D

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值