在做状态压缩时看到了这道题:
总结一下:
状态压缩特点:
某一维或几维非常小
最优性原理,无后效性
(遍历的点的具体顺序对以后的决策是没有影响的)
基于连通性的状态压缩详解:http://www.doc88.com/p-9009338580746.html
题意:给出一个n*m的矩形,然后用1*2大小的多米若骨牌去填充n*m的这个矩形,问有多少种填充方法。
分析参考:http://blog.csdn.net/u013480600/article/details/19499899
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 15;
long long d[2][1<<maxn];
int n,m,cur;
void update(int a,int b)//a是包含m位1进制数的老状态,b是包含m+1位1进制数的新状态
{
if(b&(1<<m)) d[cur][b^(1<<m)] += d[1-cur][a];//只有新轮廓线首位为1时才更新
}
int main()
{
while( scanf("%d%d",&n,&m)==2&&n&&m )
{
if(m>n)swap(n,m);
memset(d,0,sizeof(d));
cur=0;
d[cur][(1<<m)-1]=1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cur ^=1;
memset(d[cur],0,sizeof(d[cur]));
for(int k=0;k<(1<<m);k++)//k的二进制形式表示前一个格子的轮廓线状态
{
update(k,k<<1);//当前格不放,直接k左移一位就表示带m+1位的新轮廓线的状态
if(i && !(k&(1<<(m-1)) )) update(k,(k<<1)^(1<<m)^1);//上放,要求轮廓线首为0
if(j && (!(k&1)) ) update(k,(k<<1)^3);//左放,要求轮廓线尾0,首1
}
}
printf("%I64d\n",d[cur][(1<<m)-1]);
}
return 0;
}