寒假2019培训:令人崩溃的状压dp

本文介绍了状压DP的概念,以及如何利用位运算进行状态压缩。通过几个例题,如TSP问题、关灯问题、农场种植方案、宝藏问题、广场铺砖问题等,深入阐述了状压DP的应用,并探讨了优化方法和拓扑排序方案数问题。适合算法初学者和进阶者学习。
摘要由CSDN通过智能技术生成

来自上海交大的柳哥哥,今天给我们讲了状压dp真的很难听懂啊~~

在DP进行状态表示的时候,总会遇到一些只使用f [ i ] [ j ] 无法表示的状态。

▪例如:用 DP方法解决TSP 问题

▪这里设置的状态中需要记录下来前面已经走过的城市,所以需要一种方便简洁的手段来表示此信息。

所以,状态压缩dp就要补充一点位运算了:

 

▪<< 左移

▪>> 右移

▪& 与

▪|   或

▪~ 非

我们所需要做的是

▪以位运算来记录下来所有城市中哪些城市走了,哪些城市没走。

▪例如 二进制数(10010) 表示第2个,第5个城市已经经过,其他城市未经过。

这里要先学一些组合的操作:

▪(1<<( i  ) )等价于 2^i

▪x | ( (1<<( i  ) ) )  将 x 的第 i+1 位强行变成 1

▪if ( x & (1 << ( i - 1 )  )  ) 检测x的第 i 位是否为 1

▪for( int i = S  ;  i ;  i =(i-1)&S ) 枚举子集

▪-x 等价于(~x)+1   (x&-x) 只保留x 的最后一位

^ 异或

证明过程,可以有兴趣上网搜索,有空,我也会更新贴上~

————————————————————2019.1.27第一次更新———————————————————

————————————————————已经经历二次更新———————————————————

例题1 :求解TSP问题

▪有n个城市,从起点 0 开始游历每一个城市,只访问每个城市一次,最后回到起点,所需要的最短路径是多少?

▪n<=15

这题,n很小,老师也跟我讲,他选择了状压dp

▪设 f [ i ] [ S ] 表示当前在 i 点处 , 已经经过的城市信息 用 S保存 的最短路径。

▪假设 用 c [ i ] [ j ] 表示一条 从 i 点到 j 点的有向边。

▪ 则

用 f [ i ] [ S ] 更新 f [ j ] [ S | ( 1 << j - 1 ) ]


 

例题2 关灯问题

▪现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——

▪按下了第i个按钮,对于所有的灯都有一个效果。按下i按钮对于

▪第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开

▪了的时候,把它关上,否则不管;如果为-1的话,如果这盏灯是

▪关的,那么把它打开,否则也不管;如果是0,无论这灯是否开,

▪都不管。

▪现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问

▪最少要按几下按钮才能全部关掉。

▪n<=15,m<=100

 

设 f [ S ] 表示从初始状态到达 S 状态的最小步数。

▪具体操作类似 B F S 。

例题3

例题3

▪农场主John新买了一块长方形的新牧场,这块牧场被划分成M行

▪N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。

▪John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

▪遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜

▪欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也

▪就是说,没有哪两块草地有公共边。

▪John想知道,如果不考虑草地的总块数,那么,一共有多少种种

▪植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

 

▪假如上一行是确定的,我们就可以判断下一行是否合法。

▪所以设 f [ i ] [ S ] 表示第 i 行状态为 S 时的方案数。

▪转移时,枚举上下两行,复杂度较高。

 

 

 

例题4:NOIP 2017 宝藏

▪给出一副无向图,每条边都有一个权值且均未开通,先可以随便取一

▪个起点,要开通一些边,使它成为一个连通图,开通一条边的代价为

▪这条边的权值*起点到它的点的个数(起点也算),求最小代价.

▪边数m<=1000

▪点数

–70% n<=8

–100% n<=12

▪关键点是考虑如何划分阶段。

▪方案1:枚举起点,用S记录树的形态,树形态总数为2^28级别(n=8)

▪方案2:考虑以每次选择一条新开通的边为阶段,那么对于每个节点,我要记录当前第 i 个节点与起点的距离。

▪考虑70%数据情况下,状态总数为8^8级别,可做。

▪设f [ S ] 表示当前节点与起点的距离为状态为S的情况下的最小花费。 这里 S 需要使用 8 进制压缩。

 

▪方案3:考虑每次集中处理所有与起点距离为 k 的节点。

▪设 f [ i ] [ S ]表示处理到了与起点距离为 i 的节点,已经与起点相连通的节点集合 为 S 的最小花费。

▪每次枚举所有不在S中的点构成的集合S'作为第 i+1层。

▪状态转移方程为:

▪把S集合和S' 集合相连的最小的距离是另外一个DP。

 

 

关于一些优化

▪状压DP用递推写的一个通病是会访问大量的无效状态。

▪这时候记忆化搜索会显得非常优秀。

 

广场铺砖

▪有一个W行H列的广场,需要用1*2小砖铺盖,小砖之间互相不能重叠,问有多少种不同的铺法? (1<=W,H<=11)

▪1*2的小砖横放不会影响下一行,竖放会影响下一行的初始状态。

▪设 f [ i ] [ S ] 表示当前第 i 行状态为S,前 1 - i-1行已经填满的方案数。

▪假如从第 i 行 的S状态到 第 i+1行的S’状态有g[S][S’]种方案。

▪则有 f[i+1][S’]+=f[i][S]*g[S][S’];

▪考虑求出 g[S][S’]。

▪每次枚举起点状态S,考虑DFS,每次从 (S, 0)的初始状态通过不断加入横放或者竖放的骨牌,到达((1<<m)-1,S’)的状态,然后g[S][S’]+=1。

▪一种优化方法:1.j和k执行按位与运算的结果是0.(不能同时出现两个1)

▪(这保证了每个数字1的下方必须是0,代表继续补全竖着的1*2长方形)

▪2.j和k执行按位或运算的结果的二进制表示中,每一段连续的0都必须有偶数个。

▪(这些0代表若干个横着的1*2长方形,奇数个0无法分割成这种形态。)

 

例题6:广场铺砖之加强版

▪给出n*m 的方形棋盘,用1*2的矩形的骨牌和L形的骨牌(2*2骨牌少一个角)不重叠地覆盖,求覆盖满的方案数。

这道题是上面题目的加强版,我们不能继续使用优化。

▪必须使用DFS来进行转移。

 

题7:拓扑排序方案数

▪给定一个DAG图,求它的拓扑排序方案数。

 

▪设f [ S ]表示S集合内的节点都已经被排序的方案数,如果 指向j的节点都已经被排序,那么就有

▪f [ S | ( 1<< j – 1 ) ] += f [ S ]

▪DAG上的DP需要特别注意。

 

思考题:愤怒的小鸟

以上讲析均来自柳哥哥

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值