硬木地板

这就是个业界毒瘤......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 }
AC代码

某大佬把转移处理成了邻接表然后求方案数,%%%%

 

posted @ 2018-09-28 21:58  garage  阅读(95)  评论(0编辑  收藏  举报