• ZOJ 1100 Mondriaan's Dream


    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 Specification

    The input file 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 Specification

    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
    

    看的别人的代码实现的,自己有个地方还是有点没弄懂,就是为什么初始状态设为 dp[0][(1<<w)-1] = 1 ? 没有进行数组滚动优化。

    代码:

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int st[20000][2];        // 第 i 个的状态为 st[i][0] 其下一行的状态是 st[i][1]
    long long dp[12][20000];        // 第 i 行 j 状态的方法数 
    int num;
    
    void dfs(int n, int from, int to);        //从右向左填格子,填了 n 列 
    
    int h, w;
    
    int main(){
    //    freopen("input.txt", "r", stdin); 
        while(cin >> h >> w && h != 0){
            if(h*w % 2){
                cout << 0 << endl;
                continue;
            }
            num = 0;
            dfs(0, 0, 0);
            memset(dp, 0, sizeof(dp)); 
            dp[0][(1<<w)-1] = 1;    //为什么初始状态设为这个?
            for(int i=1; i<=h; i++){    //一行一行地累加 
                for(int j=0; j<num; j++){    //遍历出这一行的每种状态 
                    dp[i][st[j][1]] += dp[i-1][st[j][0]];    //加上到这一行的 st[j][1] 状态的上一行的方法数
                }
            }
            cout << dp[h][(1<<w)-1] << endl;    //输出最后一行摆满时的方法数。 
        }
    } 
    
    void dfs(int n, int from, int to){
        if(n == w){        //正好 w 列了 
            st[num][0] = from;        //将状态存起来 
            st[num][1] = to;
            num++;
            return ;
        }
        if(n > w){        //超过不行 
            return ;
        } 
        dfs(n+2, (from << 2) + 3, (to << 2) + 3);        //这一行横着放,则下一行的这两列也可以横着放一个
        dfs(n+1, (from << 1) + 1, (to << 1));            //竖着放,则下一行的这一列就放不了了
        dfs(n+1, (from << 1), (to << 1) + 1);            //这一列不放,则下一行的这一列可以竖着放一个 
    }
  • 相关阅读:
    Mockito
    输入一个链表,输出该链表中倒数第k个结点。
    序列化
    全排列
    PostgreSQL libpq学习指南二
    PostgreSQL libpq 客户端接口(一)
    PostgreSQL 中的shared buffer
    通过 Unwrapper 解密 DBMS 程序包
    openGuassDB介绍及安装实践
    PostgreSQL中的ACID特性介绍
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/7224343.html
Copyright © 2020-2023  润新知