Description
The banquet hall of Computer Scientists' Palace has a rectangular form of the size M x N (1<=M<=9, 1<=N<=9). It is necessary to lay hardwood floors in the hall. There are wood pieces of two forms:
1) rectangles (2x1)
2) corners (squares 2x2 without one 1x1 square)
You have to determine X - the number of ways to cover the banquet hall.
Remarks. The number of pieces is large enough. It is not allowed to leave empty places, or to cover any part of a surface twice, or to saw pieces.
Input
The first line contains natural number M. The second line contains a natural number N.
Output
First line should contain the number X, or 0 if there are no solutions.
Sample Input
2 3
Sample Output
5
题意:
给出 n*m (1≤n、m≤9)的方格棋盘,用 1*2 的矩形的骨牌和 L 形的(2*2 的
去掉一个角)骨牌不重叠地覆盖,求覆盖满的方案数。
Solution:
还是状态压缩,这次的情况比较多,要全部列出。
b1,b2分别代表上下两行前列对下一列的影响
s1,s2对应上下两行的状态
情况 |
上列b1,b2要求 |
状态改变 | 对下一列的影响 |
10 10 |
b1=0, b2=0; |
s1<<1, s2<<1|1; |
b1=0, b2=0; |
11 10 |
b1=0, b2=0; |
s1<<1, s2<<1|1; |
b1=1, b2=0; |
10 11 |
b1=0, b2=0; |
s1<<1, s2<<1|1; |
b1=0, b2=1; |
00 11 |
b2=0; | s1<<1|1-b1, s2<<1|1; |
b1=0, b2=1; |
01 11 |
b2=0; | s1<<1|1-b1, s2<<1|1; |
b1=1, b2=1; |
11 01 |
b1=0; | s1<<1, s2<<1|b2; |
b1=1, b2=1; |
00 00 |
无 | s1<<1|1-b1, s2<<1|b2; |
b1=0, b2=0; |
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<set> #include <queue> #include<algorithm> #include <vector> const double PI = acos(-1.0); using namespace std; long long dp[10][1 << 11], tep;//用tep记录上一行每个状态的dp值 int n, m; void dfs(int k, int s1, int s2, int b1, int b2, int line)//s1为前一行状态, s2为当前行状态 { if(k >= m) { if(!b1 && !b2) dp[line][s2] += dp[line - 1][s1]; return; } if(!b2) { if(!b1) { dfs(k + 1, s1 << 1, s2 << 1 | 1, 0, 0, line); dfs(k + 1, s1 << 1, s2 << 1 | 1, 1, 0, line); dfs(k + 1, s1 << 1, s2 << 1 | 1, 0, 1, line); } dfs(k + 1,(s1 << 1 | 1) - b1,s2 << 1 | 1, 0, 1, line); dfs(k + 1,(s1 << 1 | 1) - b1,s2 << 1 | 1, 1, 1, line); } if(!b1) dfs(k + 1,s1 << 1,s2 << 1 | b2, 1 ,1 , line); dfs(k + 1,(s1 << 1 | 1)- b1, s2 << 1| b2, 0, 0, line); } int main() { int i, j, k; while(~scanf("%d%d", &n, &m)) { memset(dp, 0, sizeof(dp)); tep = 1; dp[0][(1 << m) - 1] = 1; for(i = 1; i <= n; ++ i) dfs(0, 0, 0, 0, 0, i); printf("%I64d\n", dp[n][(1 << m)- 1]); } }