题意:用1*2的小矩形拼成n*m(n,m<=11)的矩阵有多少种方案。
解法:状态压缩,dfs求转移。当前一列的状态确定后,后一列必须用横向的矩形来填补前一列的空白格,所以前一列不为空时,这一列可以选择也为空让下一列来填补,或是本列来个纵向的矩形填补(如果有连续的两个空格的话)。
代码:
/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=100010;
const LL INF=0x3FFFFFFF;
LL dp[2][(1<<12)];
int n,m;
void dfs(int now,int wei,int st,LL num)
{
if(wei==m)
{
dp[now][st]+=num;
return ;
}
dfs(now,wei+1,st,num);
if(wei<m-1&&!(st&(1<<wei))&&!(st&(1<<(wei+1))))
dfs(now,wei+2,st|(1<<wei)|(1<<(wei+1)),num);
}
int main()
{
while(cin>>n>>m&&n+m)
{
int now=0;
memset(dp,0,sizeof dp);
dfs(now,0,0,1);
for(int i=1; i<n; i++)
{
memset(dp[now^1],0,sizeof dp[now]);
for(int j=0; j<(1<<m); j++)
if(dp[now][j])
dfs(now^1,0,(~j)&((1<<m)-1),dp[now][j]);
now^=1;
}
printf("%I64d\n",dp[now][(1<<m)-1]);
}
return 0;
}
/*
n*1+((n-1)/2+(n-2)/3)*/