状压DP
状压DP这玩意儿说实话没什么总结的,不过还是要说说
既然是状压,那么就少不了位运算,所以位运算要熟悉
| 类 型 | 运算符 | 含义 |
| 位逻辑 运算符 | & | 按位与 |
| | | 按位或 | |
| ^ | 按位异或 | |
| ~ | 取反 | |
| 移位运 算 符 | << | 左移 |
| >> | 右移 |
总结起来说,就是先把它写成二进制(8位),然后按下表规则进行运算
| 类型 | 符号 | 规则 | 例子 |
| 按位与 | & | 同1为1,其余为0 | 9 00001001 & 5 00000101 1 00000001 |
| 按位或 | | | 同0则0,其余为1 | | 5 00000101 13 00001101 |
| 按位异或 | ^ | 不同则1,相同则0 | ^ 5 00000101 12 00001100 |
| 取反~ | ~ | 0变1,1变0 | 9 00001001 ~ 246 11110110 |
| 左移 | << | 丢掉最右,整体右移 |
>> 2 00000010 |
| 右移 | >> | 丢掉最左,整体左移 | 9 00001001 << 2 00100100 |
再说说一些实战中的小技巧把
比如【SCOI2005互不侵犯】一题中,放置一个国王后,它那一行内的左右不能再放,直白点就是每一行不能有相邻两个1出现
当然我们可以枚举每一种情况,然后判断是否有相邻的两个1,但是有时候情况就会很多,如【炮兵阵地POJ1185】,但是可行的情况却不多,所以我们可以先把每一行中可行的找出来
如何找呢?想到dfs没?这可是一个找所有方案的利器啊!
比如当n=4的时候,我们要找出0000,0001,0010,0100,0101,1000,1001,1010这些方案
具体怎么找就不说了,看看代码
| void dfs(int x,int s) { if(x==n) { 记录下s return; } dfs(x+1,s<<1); if(!(s&1)) dfs(x+1,(s<<1)+1); } |
主程序调用dfs(0,0)即可
然后就是写代码的一些技巧,动态规划出了可以写递推以外,还可以以记忆化的形式实现,比如说【棋盘游戏】一题(下面有链接),我考试的时候写递推就写昏了,但是改成记忆化,也就是dfs的形式,很轻松就写出来了
我做过的一些状压:
棋盘游戏 board http://blog.csdn.net/jiangzh7/article/details/8592387
[SCOI2005]互不侵犯 king http://blog.csdn.net/jiangzh7/article/details/8619644
Mondriaan's Dream POJ2411【基础状压】 http://blog.csdn.net/jiangzh7/article/details/8629641
炮兵阵地 POJ1185 http://blog.csdn.net/jiangzh7/article/details/8629872
售货员的难题【本来是搜索的】 http://blog.csdn.net/jiangzh7/article/details/8631048
Corn Fields POJ3254 http://blog.csdn.net/jiangzh7/article/details/8631768
扫雷 SCOI2005 http://blog.csdn.net/jiangzh7/article/details/8731992

本文深入探讨状压DP及其位运算的应用,通过实战案例解析如何利用DFS解决复杂问题,并展示动态规划的多种实现方式。同时分享作者在解决棋盘游戏、互不侵犯、炮兵阵地等经典问题中的经验,以及对状压DP技术的实践理解。
352

被折叠的 条评论
为什么被折叠?



