這就是個業界毒瘤......50行的狀壓DP。html
題意:用(1*2的棋子)和(2*2挖掉1*1的棋子)鋪滿n * m的方案數。n,m<=9。ide
提及來跟以前那個廣場鋪磚問題幾乎如出一轍,而後再借鑑芯片中的pre思想便可。函數
可是呢......特殊狀況一個接一個,硬是打了一個小時才寫出來。spa
在DFS轉移的時候,因爲要知足"鋪滿"性質,咱們要保證i - 1行所有填滿。code
通常轉移的時候只要注意(x - 1, y - 1)便可,而後頭尾要特判。htm
提及來簡單,寫起來一個DFS函數95行可不是說着玩的......blog
而後就很高興的A了。記得開long longget
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 }
某大佬把轉移處理成了鄰接表而後求方案數,%%%%it