【基础】状压DP——二进制的妙用

如果想了解更多内容,欢迎关注我的微信公众号:信息学竞赛从入门到巅峰。

 

之前我们讲解了背包问题、树形DP,区间DP这三类问题。这些都是中规中矩的动态规划题目。

今天,我为大家讲解一种比较有趣、比较容易辨别的动规问题——状压DP。

状压DP,非常容易理解,就是在状态比较多的情况下,同时状态只需要记录是或非,使用二进制将其压缩,从而达到缩减时间复杂度的效果。

由于要使用二进制来表示状态,所以这类问题的数据范围会相对较小,时间复杂度经常含有 2^N ,故容易辨别(但是别把纯正的搜索题想成DP哦)。

 

下面,我通过几道例题来深入讲解一下状压DP(例题来源洛谷,侵删)。

 

 洛谷P1433

观察题目发现,n最大只有15,很显然的状压DP。

我们用15位二进制数来表示奶酪的状态。换句话说,第i位二进制位如果是1,表示第i个奶酪已经被吃掉了;否则表示第i个奶酪还没被吃掉。

通过一个15位的二进制数,我们已经把奶酪的状态表示出来了,那么我们还需要什么数据才能实现递推呢?我们考虑吃奶酪的过程,吃完一个奶酪和到下一个奶酪的地方去的这个过程,我们只需要知道当前吃的奶酪是哪一个,和之前已经吃过的奶酪的顺序是没有关系的。

通过分析,这道题的解法已经很显然了,我们定义f[i][j]表示当前已经吃掉的奶酪的状态为i,最后吃的奶酪是j,转移方程如下:

 

 洛谷P1433

这是一道计数类问题,每块土地分为种了或没种,且数据范围较小,所以判断这是一道状压DP的题目。

按照套路,接下来要设计状态。

我们发现如果把整个矩阵(题目种农夫的地可以当成一个n*m的矩阵)进行压缩,那显然是压不了的。考虑矩阵中的一行,我们发现这行只受到它上下两行的限制(如果存在的话)。那么,我们如果从上往下DP,一行的状态就只受到它上一行的限制。这样我们就能DP了。

定义f[i][j]表示当前在处理第i行,上一行的状态为j,转移方程如下:

这道题还有一个要注意的点就是初值的设置:

 

总结:状态DP的关键点在于如何对状态进行压缩、选择何种状态进行压缩。

现在很多的题目都不是单独的一种DP类型,而是在DP上继续做文章,如通过数据结构优化时间复杂度等等,我将会在后续的文章中给出动态规划的综合题,帮助大家掌握动态规划题目。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值