zoukankan      html  css  js  c++  java
  • 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);            //这一列不放,则下一行的这一列可以竖着放一个 
    }
  • 相关阅读:
    【LeetCode-动态规划】编辑代价
    【C++】使用istringstream分割字符串
    【LeetCode-字符串】简化路径
    【LeetCode-字符串】简化路径
    【LeetCode-并查集】朋友圈
    【LeetCode-背包】目标和
    【LeetCode-动态规划】分割等和子集
    The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes
    【错误解决】本地计算机上的mysql服务启动停止后,某些服务在未由其他服务或程序使用时将自动停止
    MySQL解压版安装配置详解
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/7224343.html
Copyright © 2011-2022 走看看