状态压缩动态规划

原理讲解

   状态压缩DP其实就是把一种状态通过二进制的形式储存下来,从而利于进行状态的转移。
   例如5个盒子排成一排,其中第1,3,4个盒子有糖果,那么可以表示为 10110 转换为十进制就是 22

这类问题通常有一定的模板,在以下情况可能要用到状压DP:

  • 所输入的内容只有两种状态,就比如只有 10
  • 统计合法状态的方案数 or 最大值。
  • 不能用其他方法。

  解决这类问题的状态一般都设置为如 dpij... ,其中 i 表示第几排/个,j 表示第 i 排/个 的状态,如果有其它条件的话可能还需要扩展维度。其状态转移方程一般也类似于 dpij+=dpi1k cnt 表示合法状态数,当然,其最终答案就类似于 i=1cntdpni ,这肯定不是绝对的,具体还要看是求数量|最大值,还是别的。

  那么,状压DP有什么缺点呢?其实也很容易发现:即使是长整型 long long 也只有64位,也就是说最多只能存64个状态,这真是一个致命缺点(什么,你用bitset??)。

例题解析

  理论会了,就开始实践吧!
  来看这题 Corn Fields G,这题可以说是超超超经典的一道状压DP题。首先,也是这题的关键,就是将土地状态转化为十进制储存,如将111转化为7。要计算方案总数,那一要先判断那种状态是合法的,判断一种状态是否合法要考虑三个问题,行内合法以,行间兼容,和是否在肥沃的土壤上,也就是这一步体现了题目所说的"位运算的妙用"。

行内兼容

举个栗子:在 0000211112中共有8种合法状态 0000,0001,0010,0100,0101,1000,1001,1010,要怎么筛选出它们呢?回忆一下 & 运算符的运算规则:相同为1否则为零,再往深了想一下是不是只要 i&(i>>1)=0 ,就表明状态 i是合法的?就比如 1010&0101=0。是不是豁然开朗了。 i&(i<<1)=0也是可以的。

行间兼容

有了前面的经验的经验这个就简单了,只要 i$j=0i 行就和第 j 行相兼容,就比如说 1010&0100=0这两行就可以兼容。

是否在肥沃的土壤上

这个也很好理解,完成这一步骤还是要用到 &运算。
我们来找一下规律:
10010&10000=10000,01100&10000=0,00000&10000=0
10010&11111=100100,01100&111111=01100,00000&11111=0
  你发现了什么?没错对于土地状态 i和当前状态j 只要 i&j==j,那么状态j就是OK的。


这样就可以愉快的设计算法了:

  • 定义 dpij 为第i行第j种状态的方案数。
  • 初始状态 dp1i=1,即第1行的每种状态都是一种方案
  • 状态转移方程 dpij+=dpi1k
  • 最终答案 i=1cntdpni

参考代码

#include<bits/stdc++.h>
using namespace std;
const int mod=100000000;
int num[13],dp[13][1<<13],ans=0;
int g[1<<13];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int tmp; cin>>tmp;
num[i]=(num[i]<<1)+tmp;
}
}
for(int i=0;i<(1<<m);i++){
if(!(i&(i>>1))&&!(i&(i<<1))){
g[i]=1;
if((i&num[1])==i)
dp[1][i]=1;
}
}
for(int x=2;x<=n;x++){
for(int j=0;j<(1<<m);j++){
if(((j&num[x-1])==j)&&g[j]==1){
for(int y=0;y<(1<<m);y++){
if(((y&num[x])==y)&&!(j&y)&&g[y]){
dp[x][y]=(dp[x][y]+dp[x-1][j])%mod;
}
}
}
}
}
for(int i=0;i<(1<<m);i++)
ans=(ans+dp[n][i])%mod;
printf("%d\n",ans);
return 0;
}

更多题目

互不侵犯
炮兵阵地
Matching
Mixed Up Cows G

posted @   全角的!与半角的!  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示