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 }