状压DP蒙德里安的梦想
Posted HX-Note
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压DP蒙德里安的梦想相关的知识,希望对你有一定的参考价值。
状态压缩的核心是对二进制的理解,我们把一个状态表示成二进制,从而用一个整数表示出各种状态。
导读 ^ _ ^
何为状态压缩?
状态压缩的核心是对二进制的理解
我们把一个状态表示成二进制
从而用一个整数表示出各种状态
在dp操作做,我们用位运算的角度去判断并且执行相应的操作
蒙德里安的梦想
思路
如果横着放确定,那么剩下的就是只能竖着放
如何表示每行状态,我们将其用二进制去思考,即每个数都是二进制。
分类讨论:
位运算的补充说明:
所以要提取处理一下st布尔数组
为什么后面还要对cnt进行判断?
因为每次都是从1开始判断,需要处理一下最后的一段
代码实现
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 12, M = 1 << 12;
long long f[N][M];
bool st[M];
int n,m;
int main( )
while(cin >> n >> m, n || m)
memset(f, 0, sizeof(f));
//预处理st数组,对某种状态不能竖着放的排除
for (int i = 0; i < 1<<n; i++)
int cnt = 0;
st[i] = true;
for (int j = 0; j < n; j++)
if(i >> j & 1)
if(cnt & 1) st[i] = false;
cnt = 0;
else cnt++;
if(cnt & 1) st[i] = false;
f[0][0] = 1;//棋盘是从第0列开始,没有-1列,所以第0列第0行,不会有延伸出来的小方块,即1
for (int i = 1; i <= m; i++)
for (int j = 0; j < 1 <<n; j++)
for (int k = 0; k < 1<<n; k++)
if((j & k)==0 && st[j | k])
f[i][j] += f[i-1][k];
cout << f[m][0]<< endl;
//f[m][0]表示 前m-1列的方案数已经确定,从m-1列伸出,并且第m列的状态是0的所有方案数
return 0;
#谢谢你的观看!
^ _ ^
以上是关于状压DP蒙德里安的梦想的主要内容,如果未能解决你的问题,请参考以下文章
DP问题从入门到精通4(状态压缩dp,蒙德里安,最短Hamilton路径)