#include <iostream>
#include <cstring>
using namespace std;
const int N = 12,M = 1 << N;
bool st[M];//表示所有列的状态
long long f[N][M];
int n,m;
int main()
{
while(cin >> n >> m , (n || m))
{
for (int i = 0;i < 1 << n;i ++)//枚举所有状态判断是否合法
{
int cnt = 0;
st[i] = true;
for (int j = 0; j < n;j ++ )//枚举i状态下一列的所有状态
{
if((i >> j) & 1) //如果该位是以判断是否合法,我们保证每种状态下不会出现奇数个连续的0
{
if(cnt & 1){
st[i] = false;
break;
}
}
else cnt ++;
}
if(cnt & 1)//判断最后一段连续的0是否为奇数
st[i] = false;
}
memset(f ,0 ,sizeof f );
f[0][0] = 1;//当处于 0 0 时有一种摆法
for (int i = 1;i <= m;i ++ )//枚举所有列
for (int j = 0;j < 1 << n;j ++ )//枚举当前列可能取得的所有状态的状态
for (int k = 0;k < 1 << n;k ++)//枚举前列的状态
if((k & j) == 0 && st[k | j])
f[i][j] += f[i - 1][k]; // 当前列的方案数就等于之前的第i-1列所有状态k的累加。
//当k & j != 0 时说明有冲突
//我们以二进制形式表示每一列凸向下一列的状态
cout << f[m][0] <<endl;
}
return 0;
}
蒙德里安的梦想(状态压缩dp)
最新推荐文章于 2024-08-18 21:04:25 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)