zoukankan      html  css  js  c++  java
  • poj 2411 Mondriaan's Dream

    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
    

    Source

    使用状态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);
    }


  • 相关阅读:
    Java和Flex积分误差(一个)
    分组统计查询(本章小结)
    crm使用soap删除实体
    宁可信其有,谎言重复千遍就会成为真理,性格可以被改变
    意想不到的一天,无法逃出的肖申克
    测试使用wiz来发布blog
    2013年7月4日星期四
    2013年7月3日星期三
    2013年7月2日星期二
    2013年7月1日星期一
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3015680.html
Copyright © 2011-2022 走看看