Always ke|

Creeper_l

园龄:1年4个月粉丝:10关注:13

状压 DP 学习笔记

前言

2023.8.30 开始停课集训。

开始补 \(CSP-S\) 的知识点,先打算来学状压 \(DP\)

定义

状压 \(DP\) 的全称是状态压缩动态规划,也是动态规划中的一种。但是其与普通 \(DP\) 不同的是它将某种状态(一般为二进制 \(01\) 串,\(1\) 表示选,\(0\) 表示不选。也有其它进制)作为了 \(dp\) 数组的下标,这样更方便两种不同状态之间的转移。因为状态是用二进制表示的,所以状压 \(DP\) 的时间复杂度一般为 \(O(n \times 2^{n})\) 或者 \(O(n^{2} \times 2^{n})\)。所以状压 \(DP\) 最大能接受的数据范围是 \(n<=20\)。一般情况下看到数据范围小于 \(20\) 的时候都可以考虑状压。

位运算

状压的实现在于位运算,只有将位运算弄清楚了,才能写好状压。

  • 左移 / 右移

左移和右移的定义是在二进制表示下将一个数向左 / 右移。所以左移 \(x\) 位相当于多添 \(x\)\(0\),右移 \(x\) 位相当于减少 \(x\) 位。

比如 \((11001011)_{2}\) 左移 \(3\) 位后为:\((11001011000)_{2}\)\((11001011)_{2}\) 右移 \(3\) 位后为:\((11001)_{2}\)

可以发现,左移和右移相当于乘/除以 \(2^{x}\)

  • \(&\) / 或 \(|\) / 非 \(!\) / 异或 \(^\)

\(&\):两位都为 \(1\) 结果才为 \(1\)

\(|\):两位至少有一位为 \(1\) 结果才为 \(1\)

\(!\):非 \(1\)\(0\),非 \(0\)\(1\)

异或 \(^\):两位不同,结果才为 \(1\)

位运算常用技巧

  • 询问第 \(i\) 位是否为 \(1\)x & (1 << i - 1)

  • 询问两个数是否在同一个位置上都是 \(1\)x & y

  • 将第 \(i\) 位变成 \(1\),其余位不变:x ^ (1 << i - 1)

  • 这个数的最后一个 \(1\) 以及后面的 \(0\)x & -x

  • 询问这个数一共包含了多少个 \(1\)__builtin_popcount(x)

做法

状压 \(DP\) 很多时候需要初始化两个数组 \(sit\)\(sta\)\(sit_{i}\) 表示 \(i\) 所对应的十进制数是多少,\(sta_{i}\) 表示 \(i\) 中包含多少个 \(1\)。有了这两个数组后 \(dp\) 会变得更容易。而这个过程一般用一个 \(dfs\) 来实现。但这两个数组的定义有一个前提:\(i\) 状态一定合法。

Code

inline void Dfs(int x,int num,int cur)
{
	if(cur >= m)
	{
		sit[++cnt] = x;
		sta[cnt] = num;
		return; 
	}
	Dfs(x,num,cur + 1);
	Dfs(x + (1 << cur),num + 1,cur + 2);
} 

\(dp\) 部分一般会先枚举 \(n\)(也就是每个位置),再枚举状态。如果从状态 \(j\) 到状态 \(k\) 是合法的,那么就转移 \(dp\) 值。判断合不合法可以写在一个 \(Compatible\) 函数里,也可以直接写在循环里。

Code

inline bool Compatible(int j,int x)
{
	if(sit[j] & sit[x]) return false;
	if((sit[j] << 1) & sit[x]) return false;
	if((sit[x] << 1) & sit[j]) return false;
	return true;
}

状压 \(DP\) 还会用到枚举子集。如果直接枚举的活可能会 \(TLE\),但是我们可以对做法进行优化:

for(int j = i & (i - 1);j;j = (j - 1) & x)

这样就不会枚举到一些不合法的序列,时间复杂度从\(O(4^{n})\) 优化到了 \(O(3^{n})\),证明略。

总结

状压 \(DP\) 总体来说还是比较板的,无论是状态还是转移。而且这一类题的特点一般都很明显,一眼就可以看出来是状压,特别是数据范围。但是题型还是很多变的。

例题

【提高组——专题训练】状态压缩DP

本文作者:Creeper_l

本文链接:https://www.cnblogs.com/Creeperl/p/17913368.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Creeper_l  阅读(22)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
  3. 3 True love tired
  4. 4 一笑江湖 (DJ弹鼓版) 闻人听書_
  5. 5 最好的安排 曲婉婷
  6. 6 星星在唱歌 司南
  7. 7 山川 李荣浩
  8. 8 On My Way Alan Walker
  9. 9 百战成诗 王者荣耀·100英雄官方群像献礼歌
  10. 10 雪 Distance Capper / 罗言
  11. 11 Edamame bbno$ / Rich Brian
  12. 12 半生雪 七叔-叶泽浩
  13. 13 Catch My Breath Kelly Clarkson
  14. 14 Love Is Gone SLANDER / Dylan Matthew
  15. 15 Endless Summer Alan Walker / Zak Abel
  16. 16 悬溺 葛东琪
  17. 17 风吹丹顶鹤 葛东琪
  18. 18 Normal No More TYSM
  19. 19 哪里都是你 队长
  20. 20 Stronger Kelly Clarkson
  21. 21 廖俊涛
  22. 22 消愁 毛不易
  23. 23 The Runner Yubik
  24. 24 踏山河 七叔-叶泽浩
  25. 25 Waiting For Love Avicii
  26. 26 在你的身边 盛哲
  27. 27 Dream It Possible Delacey
  28. 28 凄美地 郭顶
  29. 29 满天星辰不及你 ycc
  30. 30 侧脸 于果
  31. 31 阿拉斯加海湾 蓝心羽
  32. 32 虞兮叹 闻人听書_
  33. 33 离别开出花 就是南方凯
  34. 34 盗墓笔记·十年人间 李常超 (Lao乾妈)
最好的安排 - 曲婉婷
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起