zoukankan      html  css  js  c++  java
  • POJ 2411Mondriaan'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

    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*2的小木块,有几种方法能构成h*w的长方体。
    相当蛋疼的题目,可能是我比较菜吧,想了好久才找到适合DP的状态,而且状态数太多了,把内存的给爆了,迫不得以,用预处理去掉一维,内存才够用
    状态的表示:
    b是当前dp的矩形的宽度
    dp[h][state]
    h代表当前高度
    state是三进制数来表示当前高度上每列的状态
    2代表与当前高度同高
    1代表比当前高度矮一格
    0代表比当前高度矮两格
    比如当
    b=4
    h=2
    三进制2222,2221
    分别代表2*4的矩形,和缺了一个角的2*4矩形
    状态的转移:
    为了防止出现重复的计算的情况,我们要保证状态转移的唯一性。
    我想到方法是,每次操作剩下图形最高的列中最右边的列,因为这个列是唯一的,所以可以保证的转移的唯一性。
    我们对这个列操作有两种
    1,去掉这个两格,即去掉高2宽1的小木块
    2,若这个列左边相邻的列也是与其等高的列,去掉这两个列个一格,即去掉高1宽2的小木块
    代码实现:
    因为这个转移方程挺复杂的,写成递推比较麻烦,所以我写成了记忆话搜索
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 long long dp[12][90000],ans[20][20];
     6 int u[20],k[20],b;
     7 int check(int state)
     8 {
     9     int x=state,que[20]= {0},i;
    10     for(i=0; i<=10; i++)
    11     {
    12         que[i]=x%3;
    13         x/=3;
    14     }
    15     for(i=0; i<=10; i++)
    16     {
    17         if(que[i]==2)
    18         {
    19             if(que[i+1]==2)
    20                 que[i+1]=1;
    21             else
    22                 return 0;
    23         }
    24     }
    25     return 1;
    26 }
    27 long long dfs(int h,int state)
    28 {
    29     if(dp[h][state]==-1)
    30     {
    31         if(h==1)
    32         {
    33             dp[h][state]=check(state);/**当只剩下一列时,检查这列是否能用高1宽2的小木块组成*/
    34         }
    35         else
    36         {
    37             int x,i;
    38             x=state;
    39             for(i=1; i<=b; i++)/**寻找最右边且高度与h相等的那列*/
    40             {
    41                 if(x%3==2)
    42                 {
    43                     break;
    44                 }
    45                 x/=3;
    46             }
    47             if(i>b)
    48                 dp[h][state]=dfs(h-1,state+u[b]);/**没有与h等高的列,所以h下降,扫描下一高度*/
    49             else
    50             {
    51                 dp[h][state]=dfs(h,state-2*k[i]);/**去掉高2宽1的小木块*/
    52                 if(i<b&&(x/3)%3==2)/**判断与x相邻列的是否也是与等高*/
    53                 {
    54                     dp[h][state]+=dfs(h,state-k[i]-k[i+1]);/**去掉高1宽2的小木块*/
    55                 }
    56             }
    57         }
    58     }
    59     return dp[h][state];
    60 }
    61 int main()
    62 {
    63     int i,j,len;
    64     u[1]=1;
    65     k[1]=1;
    66     for(i=2; i<=11; i++)
    67     {
    68         k[i]=k[i-1]*3;
    69         u[i]=u[i-1]*3+1;
    70     }
    71     for(i=1; i<=11; i++)/**i是宽度*/
    72     {
    73         len=q[i].size();
    74         b=i;
    75         memset(dp,-1,sizeof(dp));
    76         if(i%2==1)/**判断奇偶,因为若面积是奇数则坑定种类为零,不用算了*/
    77         {
    78             for(j=2; j<=i; j+=2)/**只算偶高度*/
    79             {
    80                 ans[i][j]=dfs(j,2*u[i]);
    81             }
    82         }
    83         else
    84         {
    85             for(j=1; j<=i; j++)/**j是高度*/
    86             {
    87                 ans[i][j]=dfs(j,2*u[i]);
    88             }
    89         }
    90     }
    91     while(scanf("%d%d",&i,&j)&&i)
    92     {
    93         if(i<j)
    94             swap(i,j);
    95         printf("%I64d
    ",ans[i][j]);
    96     }
    97     return 0;
    98 }

  • 相关阅读:
    VTK 图像统计_彩色直方图计算
    VTK 图像统计_灰度直方图计算
    VTK 图像基本操作_三维图像切片交互提取(回调函数、观察者-命令模式)
    VTK 图像基本操作_三维图像切片提取
    VTK 图像基本操作_图像子块提取(特征区域提取)
    VTK 图像基本操作_单颜色通道图像合成彩色
    VTK 图像基本操作_灰度图像映射成伪彩色图像(查表法)
    VTK 图像基本操作_彩色图像成分提取
    VTK 图像基本操作_彩色图像生成灰度图像
    VTK 图像基本操作_图像类型转换
  • 原文地址:https://www.cnblogs.com/qswg/p/6298753.html
Copyright © 2011-2022 走看看