状态压缩DP 小结

好久没更新博客了~
最近学了一下状压DP的内容,感觉对状态压缩有一点了解,不过有时候做题的时候总感觉有些吃力。今天做了2道TSP的题,虽然知道套路,但是对细节处理做的还是很不好,主要原因就是因为我对算法的认识还不够深刻吧,有时候碰到没有遇到过的题型的时候,总想着去查资料,没有深入思考过。其实费老强调过这一点。不要题海战术,要以一挡十。以后要改掉这个坏习惯。
言归正传。下面来总结一下,最近学状压DP的收获。
状态压缩就是将一个状态,用2进制的方法,压缩成一个数。

1.解法需要保存一定的状态数据(表示一种状态的一个数据值),每个状态数据通常情况下是可以通过2进制来表示的。这就要求状态数据的每个单元只有两种状态,比如说棋盘上的格子,放棋子或者不放,或者是硬币的正反两面。这样用0或者1来表示状态数据的每个单元,而整个状态数据就是一个一串0和1组成的二进制数。
2.解法需要将状态数据实现为一个基本数据类型,比如int,long等等,即所谓的状态压缩。状态压缩的目的一方面是缩小了数据存储的空间,另一方面是在状态对比和状态整体处理时能够提高效率。这样就要求状态数据中的单元个数不能太大,比如用int来表示一个状态的时候,状态的单元个数不能超过32(32位的机器)。

位操作实现技巧:
如果要获得第i位的数据,判断((data&(0X << i))==0),若真,为0,假,为1;
如果要设置第i位为1,data=(data|(0X1<< i));
如果要设置第i位为0,data=(data&(~(0X1<< i)));
如果要将第i位取反,data=(data^(0X1<< i);
如果要取出一个数的最后一个1(lowbit):(data&(-data))

举个例子来说。

hdu 1565 方格取数
大致题意就是:给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,所取的数所在的2个格子不能相邻,并且取出的数的和最大。
这个题就是很典型的一个状态压缩题。
对于每一行来说,每个数都有两种选择,选或者不选。那么我们就可以用0代表不选,1代表选。
比如说:10101就代表选第1,3,5个数。并且10101=21。
所以21这一个十进制的数就可以表示第一行的这个状态。
这个题的解题思路就是:
1.先枚举所有状态(从0到1<< n)找出不含相邻1的状态,那么这就是满足每一行不相邻的所有合法状态。
2.特殊处理第1行的状态。上一步找到的合法状态都可以作为是第1行的状态。
3.枚举后面的行。后面的行要满足2个条件。一就是没有相邻的1。二是和上一行的1不冲突。找到合法的状态,利用dp求出最大值就好了。

这个是最简单的套路。后面很多类似的题,都是这个套路。

状压dp的大致思想就是这样。
剩下内容写在题解里面吧~

你可能感兴趣的:(状态压缩dp)