# POJ2411 Mondriaan's Dream

Keywords: ASP.NET less

Yes, I plagiarized this question from LZL's blog. His question is really good and fragrant.

Main idea: for a rectangle of n * m, how many ways are there to fill the rectangle with 1 * 2 small squares. (1<=n, m <= 11)

Train of thought:

1. With the experience of problem-solving, I can think that this problem can not be solved by violence, because there must be many methods, and violence can not escape.

2. Seeing this problem, I think of using state transition, because a large rectangle filling can be composed of several small rectangles, which is the first idea, but this idea is far from enough.

3. Using dp, this blog explains it very clearly: https://blog.csdn.net/u014634338/article/details/50015825

4. Generally speaking, all the states of the first row are preprocessed first, and then dp starts from the second row. check() whether the row is compatible with the state of the previous row, and then add up the number of methods of the corresponding state.

There are very detailed comments in the code:

``` 1 #include<stdio.h>
2 #include<string.h>
3 #include<algorithm>
4 #define mem(a, b) memset(a, b, sizeof(a))
5 using namespace std;
6
7 int row, col;
8 long long dp[1 << 12]; //Before representative i That's ok,The first i Row status is j Number of schemes at.So the answer is dp[row][(1 << m) - 1]
9
10 int ok(int state)
11 {
12     for(int j = 0; j < col; ) //Before enumerating the status of each column j Column has been determined
13     {
14         if(state & (1 << j))  //The first j Listed as 1
15         {
16             if(j == col - 1) //Insufficient number of columns
17                 return 0;
18             if(state & (1 << (j + 1))) //The first j + 1 Listed as 1, Horizontally
19                 j += 2;
20             else//The first j + 1 Listed as 0, In the first place j It is illegal if the column has not been determined
21                 return 0;
22         }
23         else//The first j Listed as 0, Vertical placement
24         {
25             j += 1;
26         }
27     }
28     return 1;
29 }
30
31 int check(int now, int pre)
32 {
33     for(int j = 0; j < col; )//Enumerate each column to determine whether it conflicts with the previous row
34     {
35         if(now & (1 << j))//The first i Xing di j Listed as 1
36         {
37             if(pre & (1 << j))//The first i-1 Xing di j Column 1, then i Line must be horizontal
38             {
39                 if(j == col - 1)
40                     return 0;
41                 if(!(now & (1 << (j + 1))) || !(pre & (1 << (j + 1))))
42                 //The first i Xing He i-1 Row number j+1 All must be 1, otherwise it's illegal
43                     return 0;
44                 j += 2;
45             }
46             else //The first i-1 Xing di j Column is 0, description is i Xing di j The columns are placed vertically.
47                 j += 1;
48         }
49         else //The first i Xing di j Column is 0, then the i-1 Row number j Columns should be populated
50         {
51             if(pre & (1 << j))
52                 j += 1;
53             else
54                 return 0;
55         }
56     }
57     return 1;
58 }
59
60 int main()
61 {
62     while(scanf("%d%d", &row, &col) != EOF)
63     {
64         if(row == 0 && col == 0)
65             break;
66         if(col > row)  //The smaller edge of a graph is taken as the width, so the number of states in a row is less, which can improve the efficiency
67             swap(col, row);
68         if((row * col) % 2) //If the area is odd , Then there is no possibility of full coverage
69         {
70             printf("0\n");
71             continue;
72         }
73         mem(dp, 0);
74         int tot = 1 << col;
75         for(int i = 0; i < tot; i ++) //Enumerate all States on line 1,Number of scenarios to initialize line 1
76         {
77             if(ok(i))
78                 dp[i] = 1;
79         }
80         for(int i = 2; i <= row; i ++) //dp Start on line 2,Because line 1 is preprocessed
81         {
82             for(int j = 0; j < tot; j ++)//The first i Row state
83             {
84                 for(int k = 0; k < tot; k ++)//The first i - 1 Row state
85                 {
86                     if(check(j, k))
87                         dp[i][j] += dp[i - 1][k];
88                 }
89             }
90         }
91         printf("%lld\n", dp[row][(1 << col) - 1]);
92     }
93     return 0;
94 }```

Posted by kataras on Mon, 04 Nov 2019 10:10:22 -0800