poj 2411 Mondriaan's Dream

来源:互联网 发布:win10下载不了软件 编辑:程序博客网 时间:2024/04/28 17:24

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 21 31 42 22 32 42 114 110 0

Sample Output

10123514451205

Source

Ulm Local 2000
使用状态DP。DFS+DP解法分析:
对于每一个位置,我们有三种放置方法:
1. 竖直放置
2. 水平放置
3. 不放置
因为放置i行的时候只会填充i和i-1行,因此必须保证i行的放置方法能将i-1行补充满,否则放置i+1行以后的行的时候都不能再改变i-1行的状态,那么就会有没放置的空格子,不符合要求。
放置i行的时候不考虑前面行的状态对i行的影响,而是将i行随意放置,而根据规则(上面讲的,要保证i-1行放满)推出与i行状态对应的i-1行的状态。那么i行状态curRowState对应的所有情况数量,就是i-1行与i行状态curRowState对应的一个状态preRowState的所有情况数量。
curRowState = preRowState = 0
1.竖直放置
curRowState = (curRowState<<1)|1, preRowState = (preRowState<<1)|1
下一次放置column+1列,本行的column列的状态是1,前一行column列的状态也是1
2.水平放置
curRowState = (curRowState<<2)|3, preRowState = (preRowState<<2)|3
下一次放置column+2列,本行的column列和column+1列的状态都是1,前一行column列和column+1列的状态也都必须是1,否则就会有空格子,填不满
3.不放置
curRowState = curRowState<<1, preRowState = (preRowState<<1)|1
下一次放置column+1列,本行的column列的状态是0,前一行column列的状态必须是1,否则就会有空格子,填不满
使用DFS搜索每一列的三种放置方法
#include<stdio.h>#include<string.h>#define MAX 12__int64 dp[MAX][1<<MAX];int h,w;void dfs0(int column,int state);void dfs(int row,int column,int curRowState,int preRowState);int main(){     while(scanf("%d%d",&h,&w),h||w)     {          memset(dp,0,sizeof(dp));          dfs0(1,0);          for(int i=2;i<=h;i++)               dfs(i,1,0,0);          printf("%I64d\n",dp[h][(1<<w)-1]);     }     return 0;}void dfs0(int column,int state){     if(column>w+1)return;     if(column==w+1)     {          dp[1][state]++;          return;     }     dfs0(column+1,state<<1);     dfs0(column+2,state<<2|3);}void dfs(int row,int column,int curRowState,int preRowState){     if(column>w+1)return;     if(column==w+1)     {          dp[row][curRowState]+=dp[row-1][preRowState];          return;     }     dfs(row,column+1,curRowState<<1|1,preRowState<<1);     dfs(row,column+1,curRowState<<1,preRowState<<1|1);     dfs(row,column+2,curRowState<<2|3,preRowState<<2|3);}