状压dp的位运算和一些基本操作
简介
首先状压$dp$ 是针对$dp$ 中有一些状态无法表示,从而进行状态压缩;
主要有传统集合动态规划和基于连通性状态压缩的动态规划两种;
状态压缩动态规划的局限性
状态压缩的作用无非是将原本分散的状态集约化、符号化、有序化,
所以很多时候其状态数目依然是指数级别的。
同时,状态之间复杂的关系使得两两状态之间的转移也受到影响。
简而言之,状态压缩动态规划的状态与转移使得它只能处理数据在一个比较小的范围内的问题。
说白了,进行状态压缩的数组不能开很大;
状态压缩中的位运算的应用
位运算是一种处理二进制数的操作,在状态压缩中的运用就非常广泛;
左移:
符号$<<$,如 $110<<2$, 就是 $11000$ 在十进制中也就是 $6<<2=24$ ,也是$6 imes 2^2 = 24$ ;
右移:
符号$>>$,如 $110>>1$, 就是 $3$ 在十进制中也就是 $6>>1=3$ ,也是$6 div 2^1 = 3$ ;
与运算:
符号$&$ ,二进制每一位如果都为$1$ ,那么答案这一位就是$1$,否则是$0$;
等等..............
那么主要还是讲讲二进制在状态压缩中应用 (说了那么多废话,终于到正题了)
$&$的运用:将 $i$ 加入某个集合(判断第$i$位的数)
$k & (1<<(i-1)) $,也就是将 $k$ 这个二进制数中的第 $i$ 位变成 $1$;
但实际代码中我们是不需要直接将某个数加入集合,一般这种方法用在数组,或 $if$ 判断;
判断$k$集合中第 $i$ 位是否为 $1$ :$if(k& (1<<(i-1)))$
判断$k$集合中第 $i$ 位是否为 $0$ :$if(!k& (1<<(i-1)))$
$^$的运用:去掉集合中的$i$ 和 取反$k$ 集合
$k ^~(1<<(i-1))$ ,也就是将 $k$ 这个二进制数中的第 $i$ 位变成 $0$;
取反:$return~~ k^((1<<m)-1);$ $m$是要取反的位数;
以后会更新。。。。。。。。
状态压缩中集合的表示
一般状态压缩中每个集合,都是用二进制来表示;
如:$k$集合中的数是 ${1,3,5}$ ;
那么压缩成的二进制数就是 $10101$,十进制中就是 $21$;
那么代码中 $dp[21]=1$ ;
$i$在集合中,那么集合的第$i$位就是$1$;
状态压缩实际代码中的细节
左移时如果$i$ 从$1$开始一般是$<<(i-1)$ 而不是 $<<i$;
这是因为如果一开始左移 $1$ 位处理第$2$位的话,会忽略掉没有处理左移的第$1$位;
如果直接$<<n$ 的话会发现多左移了一位
在枚举集合大小是一般是 $leq ~(1<<n)-1$;
这是因为
假设$n=3$,那么集合最大就是 $111$ ;
那么$1<<n$ ,就是$1000$ ,然后减去一个$1$,就会是$111$;
以后会更新。。。。。。。。
题目
系列1
状态是每个数的使用情况
传球游戏之最小总代价
售货员的难题
[洛谷P1278]单词游戏
以后会更新。。。。。。。。。