用1*2的小长方形铺满整个n*m的大长方形吧!问有多少种方案。
用dp[i][j]表示第i行(从1开始计数)之前的所有行均已铺满,第i行目前铺的形状是j(j的二进制表示,比如01011001)。
填满第i行有三种方法,用横的小长方形和用竖的小长方形,或者兼用之。
枚举所有可以填横的小长方形的方法,设此时改行形状为xx,若某一位置不够(为0),则可用竖的小长方形填补,形成的新一行的形状为((1<<m)-1)^xx,逐行拓展即可,答案为dp[n+1][0].
#include <cstdio>
#include <cstring>
int n,m;
long long dp[13][2048];
void f(int k,int x)
{
for (int i=0;i<(1<<(m-1));i++)
{
if (i&(i<<1)) continue;
if (x&(i|i<<1)) continue;
int xx=x|i|i<<1;
dp[k][((1<<m)-1)^xx]+=dp[k-1][x];
}
}
int main()
{
while (scanf("%d%d",&n,&m)==2 && n)
{
if ((m*n)&1) {puts("0"); continue;}
memset(dp,0,sizeof(dp));
dp[0][(1<<m)-1]=1;
for (int i=1;i<=n+1;i++)
for (int j=0;j<(1<<m);j++)
f(i,j);
printf("%I64d\n",dp[n+1][0]);
}
return 0;
}