硬木地板
这就是个业界毒瘤......50行的状压DP。
题意:用(1*2的棋子)和(2*2挖掉1*1的棋子)铺满n * m的方案数。n,m<=9。
说起来跟之前那个广场铺砖问题几乎一模一样,然后再借鉴芯片中的pre思想即可。
但是呢......特殊情况一个接一个,硬是打了一个小时才写出来。
在DFS转移的时候,由于要满足"铺满"性质,我们要保证i - 1行全部填满。
一般转移的时候只要注意(x - 1, y - 1)即可,然后头尾要特判。
说起来简单,写起来一个DFS函数95行可不是说着玩的......
然后就很高兴的A了。记得开long long
1 #include <cstdio> 2 #include <algorithm> 3 4 typedef long long LL; 5 const int N = 10; 6 7 LL f[N][1200], ans; 8 int pre, m; 9 10 void DFS(int x, int y, int ns) { 11 //printf("DFS : x = %d y = %d ns = %d pre = %d \n", x, y, ns, pre); 12 if(y == m) { 13 f[x][ns] += ans; 14 //printf("DFS : f[%d][%d] = %d \n", x, ns, f[x][ns]); 15 return; 16 } 17 if(y > m) { 18 return; 19 } 20 int temp = pre; 21 if(!y) { 22 DFS(x, y + 1, ns); // space 23 if(!(pre & 1)) { 24 pre |= 1; 25 DFS(x, y + 1, ns | 1); // | 26 pre = temp; 27 } 28 return; 29 } 30 if(y + 1 == m) { 31 if(!((pre >> (y - 1)) & 1)) { 32 if(!((pre >> y) & 1)) { 33 pre |= (1 << y); 34 DFS(x, y + 1, ns | (1 << y)); // ^| 35 pre = temp; 36 if(!((ns >> (y - 1)) & 1)) { 37 pre |= (1 << y); 38 DFS(x, y + 1, ns | (1 << (y - 1))); // |^ 39 pre = temp; 40 } 41 return; 42 } 43 else { 44 if(!((ns >> (y - 1)) & 1)) { 45 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // |_ 46 } 47 return; 48 } 49 } 50 if(!((pre >> y) & 1)) { 51 pre |= (1 << y); 52 DFS(x, y + 1, ns | (1 << y)); // | 53 pre = temp; 54 if(!((ns >> (y - 1)) & 1)) { 55 pre |= (1 << y); 56 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // _| 57 pre = temp; 58 } 59 return; 60 } 61 DFS(x, y + 1, ns); // space 62 if(!((ns >> (y - 1)) & 1)) { 63 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // -- 64 } 65 return; 66 } 67 if((pre >> y) & 1) { 68 if(!((pre >> (y - 1)) & 1)) { 69 if((ns >> (y - 1)) & 1) { 70 return; 71 } 72 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // |_ 73 return; 74 } 75 if(!((ns >> (y - 1)) & 1)) { 76 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // -- 77 } 78 DFS(x, y + 1, ns); // space 79 return; 80 } 81 if(!((pre >> (y - 1)) & 1)) { 82 pre |= (1 << y); 83 DFS(x, y + 1, ns | (1 << y)); // ^| 84 pre = temp; 85 if(!((ns >> (y - 1)) & 1)) { 86 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // |_ 87 pre |= (1 << y); 88 DFS(x, y + 1, ns | (1 << (y - 1))); // |^ 89 pre = temp; 90 } 91 return; 92 } 93 DFS(x, y + 1, ns); // space 94 pre |= (1 << y); 95 DFS(x, y + 1, ns | (1 << y)); // | 96 pre = temp; 97 if(!((ns >> (y - 1)) & 1)) { 98 pre |= (1 << y); 99 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // _| 100 pre = temp; 101 DFS(x, y + 1, ns | (1 << y) | (1 << (y - 1))); // -- 102 } 103 return; 104 } 105 106 int main() { 107 int n; 108 scanf("%d%d", &n, &m); 109 if(n == 1 || m == 1) { 110 if(std::max(m, n) & 1) { 111 printf("0"); 112 } 113 else { 114 printf("1"); 115 } 116 return 0; 117 } 118 119 // prework 120 int lm = 1 << m; 121 f[0][lm - 1] = 1; 122 123 for(int i = 1; i <= n; i++) { 124 for(int j = 0; j < lm; j++) { // state of i - 1 125 //printf("f[%d][%d] = %d \n", i - 1, j, f[i - 1][j]); 126 pre = j; 127 ans = f[i - 1][j]; 128 DFS(i, 0, 0); 129 } 130 } 131 printf("%lld", f[n][lm - 1]); 132 return 0; 133 }
某大佬把转移处理成了邻接表然后求方案数,%%%%