【基础】状压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上继续做文章,如通过数据结构优化时间复杂度等等,我将会在后续的文章中给出动态规划的综合题,帮助大家掌握动态规划题目。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要证明0-1整数规划问题是NPC问题,可以采用约简证明法,即将已知的NPC问题归约为0-1整数规划问题,证明该问题也是NPC问题。 首先,我们知道背包问题是NPC问题,即在有限的背包容量下,选取一些物品使得总价值最大。将背包问题约化为0-1整数规划问题如下: 设物品集合为S={1,2,...,n},物品i的重量为wi,价值为vi,背包容量为W。引入0-1变量xi表示是否选择物品i,即xi=0或1。则0-1整数规划问题可以表示为: max Σvi * xi s.t. Σwi * xi <= W xi ∈ {0,1} 可以看出,0-1整数规划问题是背包问题的一种特殊形式,因此0-1整数规划问题也是NPC问题。 然后,我们可以将背包问题约化为0-1整数规划问题的过程中,使用动态规划方法来解决问题。具体来说,可以使用状态压缩DP来解决0-1整数规划问题。状态压缩DP是一种将集合压缩为二进制数表示的动态规划方法,可以用来解决一些具有集合结构的问题,如背包问题、旅行商问题等。 在0-1整数规划问题中,可以使用状态压缩DP来表示选取物品的情况。假设当前背包容量为j,已经考虑了前i个物品,则可以使用一个二进制数表示当前选取的物品集合,即将第k位设为1表示选取了第k个物品,为0表示没有选取。则状态转移方程为: dp[i][j][S] = max(dp[i-1][j][S], dp[i-1][j-wi][S-vi] + vi) 其中,dp[i][j][S]表示考虑前i个物品,背包容量为j,集合状态为S时的最大价值;wi和vi分别表示第i个物品的重量和价值;S-vi表示将第i个物品加入集合S后的新集合状态。 通过状态压缩DP的方法,可以在多项式时间内解决0-1整数规划问题,进一步证明了该问题是NPC问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值