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=4h=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\n",ans[i][j]);
96     }
97     return 0;
98 }

POJ 2411Mondriaan's Dream

时间: 2024-10-12 18:06:23

POJ 2411Mondriaan's Dream的相关文章

pojPOJ 2411--Mondriaan&#39;s Dream+状态压缩dp

又是一道经典的状态压缩dp 开始自己想了一下,总是觉得因为这个小矩形可以竖着放导致没法确定状态如何转移(第i行的小矩形如果竖着放,及可能影响i-1行,也有可能影响i+1行);后面看了别人的题解后,才知道原来我们可以固定小矩形竖着放的时候只能向前放,这样第i行的状态就只能影响i-1行了,也就能顺利的写出状态转移方程啦. 设dp[i][j]表示第i行处于状态j的时候,共有多少种放置方法. dp[i][j]=sum(dp[i-1][k]),其中状态j和k要能共存,并且j和k要使得第i-1行刚好铺满.

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

POJ 2411 Mondriaan&#39;s Dream

题目链接:http://poj.org/problem?id=2411 状态压缩Dynamic Programming. For each row, at ith position, 1 means that there is a block placed at this row and next row (vertically). otherwise, its 0. For the example in question, the state of For the example in que

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看

POJ 2411 Mondriaan&#39;s Dream(状压DP)

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int

POJ 题目2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13519   Accepted: 7876 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

Mondriaan&#39;s Dream - POJ 2411(状态压缩)

题目大意:有一些1*2的矩形,现在用这些小矩形覆盖M*N的大矩形,不能重复覆盖,并且要覆盖完全,求有多少种覆盖方式. 分析:可以使用1和0两种状态来表示这个位置有没有放置,1表示放置,0表示没有放置,可以有三种放置方式. 一,竖着放. 二,不放.三,横着放.直接DFS这些情况就行了................还是递归容易理解. 代码如下: =============================================================================

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

POJ 2411 Mondriaan&#39;s Dream ——状压DP 插头DP

[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出来. 加了点优(gou)化(pi),然后poj上1244ms垫底. 大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可. 然后看了 <插头DP-从入门到跳楼> 这篇博客,怒抄插头DP 然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)