思路:把行号作为dp的阶段,为了便于描述每一行的状态,我们可以用一个M位二进制数来表示这一行的状态。
如何转移:当满足一下两个条件时:
01-第i-1行的竖着的小方块(这一行状态表示为j)与第i行的竖着的小方块(这一行状态表示为k)不重叠,即 j & k == 0;
02-每一行的连续的0必须是偶数个,方便防止横着的小方块
#include <iostream>
using namespace std;
typedef long long ll;
ll f[12][1 << 11];
int n, m;
bool ck[1 << 11];
int lowbit(int x)
{
return x & -x;
}
int main()
{
while(cin >> n >> m && n)
{
// 预处理每行连续的0为偶数的情况,若存在奇数则标记为false
for(int i = 0; i < 1 << m; i++)
{
int cnt = 0, f = 0, t = i; // cnt 记录上一段连续0的数量
for(int j = 0; j < m; j++)
{
if(t >> j & 1)
{
if(cnt % 2 == 1)
{
f = 1;
break;
}
else
cnt = 0;
}
else cnt++;
}
if(f == 0 && cnt % 2 == 0) ck[i] = true;
else ck[i] = false;
}
// cout << ck[2] << endl;
f[0][0] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < 1 << m; j++)
{
f[i][j] = 0;
for(int k = 0; k < 1 << m; k++)
{
if((j & k) == 0 && ck[j | k])
f[i][j] += f[i - 1][k];
}
}
}
cout << f[n][0] << endl;
}
return 0;
}