# poj2411Mondriaan's Dream【覆盖类状压dp】

Description

Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways.

Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!

Input

The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

Output

For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

Sample Input

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0


Sample Output

1
0
1
2
3
5
144
51205


1.假设已知Fibo(n)，如果将第n+1块板竖着插入排头，会发现并没有多出组合，Fibo(n+1)=Fibo(n)，插入其他位置的情况下，

2.只有在n和n+1的位置是横板，才能多出组合，多的组合数量为Fibo(n-1);
3.推出 Fibo(n+1)=Fibo(n)+Fibo(n-1);即为Fibo(n)=Fibo(n-1)+Fibo(n-2);

1.第i行的第j列为1，第i-1行的第j列为1，这样的话，说明第i行的第j列一定不是竖放而是横放否则会与第i-1行的第j列冲突
所以马上紧接着判断第i行第j+1列，如果是1，那么满足横放的规则，同时也要第i-1行第j+1列也要为1，否则的话这个格子没办法填充，
成立后向左移动两格
不满足上述条件的，就是两个不兼容或者不合法的状态
2.第i行第j列为1，第i-1行第j列为0，那么说明第i行第j列应该竖放并填充第i-1行第j列，成立后向左移动一格
3.第i行第j列为0，说明不放方块，那么第i-1行第j列必须为1，否则没法填充这个格子。若第i-1行第j列也为0，不兼容不合法
(至于第i行第j列这个格子空着干什么，其实就是留出来给第i+1行竖放的时候插进来的)
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 15
#define MAX (1<<11)+10
long long dp[N][MAX];
long long ans[N][N];
int n,m;
bool init(int s)
{
for(int i=0;i<m;)
{
if(s&(1<<i))
{
if(i==m-1) return false;
if(s&(1<<(i+1)))i+=2;
else return false;
}
else i++;
}
return true;
}
bool ok(int s,int ss)
{
for(int i=0;i<m;)
{
if(s&(1<<i))
{
if(ss&(1<<i))
{
if(i==m-1||!(s&(1<<(i+1)))||!(ss&(1<<(i+1))))return false;
i+=2;
}
else i++;
}
else
{
if(ss&(1<<i))i++;
else return false;
}
}
return true;
}
void solve()
{
if(n<m) swap(m,n);
memset(dp,0,sizeof(dp));
int maxn=(1<<m)-1;
for(int i=0;i<=maxn;i++)
if(init(i))
dp[1][i]=1;
for(int i=2;i<=n;i++)
for(int s=0;s<=maxn;s++)
for(int ss=0;ss<=maxn;ss++)
if(ok(s,ss))
dp[i][s]+=dp[i-1][ss];
printf("%I64d\n",dp[n][maxn]);
}
int main()
{
//freopen("cin.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
if(m==0&&n==0) break;
if(m*n%2)
{
printf("0\n");
continue;
}
solve();
}
return 0;
}


#### POJ2411 状态压缩DP

2014-02-20 20:17:00

#### poj2411 2663 2420 dp+状态压缩（多米诺骨牌问题）

2013-04-19 00:04:13

#### poj2411之用1*2砖块铺满n*m-状态压缩dp

2014-03-21 08:52:26

#### POJ2411 轮廓线动态规划典型例题

2014-02-19 19:31:43

#### poj2411--Mondriaan's Dream(状压dp+dfs)

2015-02-04 20:49:28

#### poj2411(轮廓线动态规划)

2016-03-24 20:50:12

#### POJ2411:Mondriaan's Dream(状态压缩)

2014-05-04 22:44:33

#### poj2411Mondriaan's Dream题解

2015-08-01 17:43:12

#### 状态压缩动态规划 POJ 2411 （编程之美-瓷砖覆盖地板）

2012-08-08 12:37:40

#### poj2411 棋盘覆盖

2015-03-07 00:46:45