题意:由1*2的纸片组成一个n*m的矩阵(n<=11,m<=11)有多少种不同的组法;
解法:状压dp,ans[i][j]表示第i行状态为j(状态j表示为1的位向下扩展)有多少种组法。除了第一行和最后一行,都可能会有来自上方或是伸向下放的格子,剩余的格子必须可以由1*2横着铺在本行,legal函数用于判断状态是否合法;最后答案就是最后一行没有伸向下方的组法数量ans[n-1][0].
代码:
/****************************************************
* 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>
using namespace std;
#define eps 1e-8
typedef long long LL;
int legal[10000];
bool rem[40000];
int p=0;
int n,m;
bool OK(int k)
{
for(int i=0;i<m;i++)
{
if(!(k&(1<<i)))
{
if(!(k&(1<<(i+1)))&&i!=m-1)
i++;
else
return false;
}
}
return true;
}
long long ans[13][10000];
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
if(n==0&&m==0)
break;
memset(ans,0,sizeof ans);
memset(rem,0,sizeof rem);
p=0;
for(int i=0;i<(1<<m);i++)
{
if(OK(i))
legal[p++]=i,rem[i]=1;
}
for(int i=0;i<p;i++)
ans[0][legal[i]]=1;
for(int i=1;i<n;i++)
{
for(int k=0;k<(1<<m);k++)
for(int j=0;j<(1<<m);j++)
{
if(k&j) continue;
if(rem[k|j])
ans[i][j]+=ans[i-1][k];
}
}
cout<<ans[n-1][0]<<endl;
}
return 0;
}