POJ2411 Mondriaan's Dream

Keywords: ASP.NET less

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

Title Link: http://poj.org/problem?id=2411

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[13][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[1][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