题目很好理解 就是有一些1X2的小矩形 问将其填充到 NxM的大矩形 一共有多少种方案。
比较明显的状压DP,最关键的是状态的选择。我们可以吧竖着的 1x2 矩形的上半部分 当作1 吧其他状况当作0 压缩状态
然后 我们只需要保证 每一行与前一行与状态为0 按位与的结果中不存在连续奇数个0
之后,我们可以得到DP方程 f[i,j] = Σ f[i-1,k] j&k=0 && j|K 没有奇数个0
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxn = 1e5+100;
int n,m,tot;
int a[maxn];
bool check(int x)
{
int cnt=0;
for(int i=0;i<m;i++)
{
if(x&(1<<i))
{
if(cnt&1) return false;
}
else cnt++;
}
if(cnt&1) return false;
else return true;
}
long long f[50][3005];
int main()
{
while(cin>>n>>m)
{
if(n==0&&m==0) return 0;
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
tot=0;
for(int i=0;i<(1<<m);i++)
{
int val=i;
if(check(val)) a[i] = true;//,cout<<val<<" ";
}
f[0][0] = 1;
for(int i=1;i<=n;i++)
{
for(int j=0;j< 1<<m; j++)
{
for(int k=0;k< 1<<m; k++)
{
if((j&k)==0 && a[j|k]) f[i][j] += f[i-1][k];
}
}
}
cout<<f[n][0]<<endl;
}
return 0;
}
/*
2 3
*/