一般是求网格图路径个数/最值的。
维护轮廓线连通性。按照格子转移。
参考资料。
例题:bzoj1814 注意!结尾不一定是(n, m),此时要保证没有插头才能加入答案。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 6 typedef long long LL; 7 const int N = 14, M = 1600000; 8 9 LL f[2][M]; 10 int n, m, G[N][N], now[N], state[M], id[M], top; 11 char str[N]; 12 13 inline int zip(int *a) { 14 int ans = 0; 15 for(int i = m; i >= 0; i--) { 16 ans = ans * 3 + a[i]; 17 } 18 return id[ans]; 19 } 20 21 inline void DFS(int k, int cnt, int sta) { 22 if(k > m) { 23 if(cnt == 0) { 24 state[++top] = sta; 25 id[sta] = top; 26 //printf("state ++top = %d \n", state[top]); 27 } 28 return; 29 } 30 DFS(k + 1, cnt, sta * 3); 31 if(cnt) { 32 DFS(k + 1, cnt - 1, sta * 3 + 1); 33 } 34 DFS(k + 1, cnt + 1, sta * 3 + 2); 35 return; 36 } 37 38 inline void prework() { 39 DFS(0, 0, 0); 40 return; 41 } 42 43 inline void unzip(int x, int *a) { // m + 1 44 x = state[x]; 45 for(int i = 0; i <= m; i++) { 46 a[i] = x % 3; 47 x /= 3; 48 } 49 return; 50 } 51 52 inline void add(LL &a, LL b) { 53 a += b; 54 return; 55 } 56 57 inline void out() { 58 for(int i = 0; i <= m; i++) { 59 printf("%d", now[i]); 60 } 61 return; 62 } 63 64 inline int get2(int p) { 65 int cnt = 0; 66 while(1) { 67 //printf("get 2 \n"); 68 if(now[p] == 2 && !cnt) { 69 return p; 70 } 71 if(now[p] == 1) { 72 cnt++; 73 } 74 else if(now[p] == 2) { 75 cnt--; 76 } 77 p++; 78 } 79 } 80 81 inline int get1(int p) { 82 int cnt = 0; 83 while(1) { 84 //printf("get 1 \n"); 85 if(now[p] == 1 && !cnt) { 86 return p; 87 } 88 if(now[p] == 2) { 89 cnt++; 90 } 91 else if(now[p] == 1) { 92 cnt--; 93 } 94 p--; 95 } 96 } 97 98 inline char gc() { 99 char c = getchar(); 100 while(c != '*' && c != '.') c = getchar(); 101 return c; 102 } 103 104 int main() { 105 106 //printf("%d", sizeof(f) / 1048576); 107 //freopen("in.in", "r", stdin); 108 //freopen("my.out", "w", stdout); 109 110 scanf("%d%d", &n, &m); 111 for(int i = 0; i < n; i++) { 112 for(int j = 0; j < m; j++) { 113 G[i][j] = (gc() == '*'); 114 } 115 } 116 117 int last_x, last_y; 118 for(int i = n - 1; i >= 0; i--) { 119 for(int j = m - 1; j >= 0; j--) { 120 if(!G[i][j]) { 121 last_x = i; 122 last_y = j; 123 i = -1; 124 break; 125 } 126 } 127 } 128 129 prework(); 130 131 int lm = pow(3, m + 1), flag = 1; 132 LL ans = 0; 133 f[0][id[0]] = 1; 134 for(int i = 0; i < n; i++) { 135 for(int j = 0; j < m; j++) { 136 flag ^= 1; 137 for(int s = 1; s <= top; s++) { 138 f[flag ^ 1][s] = 0; 139 } 140 //printf("%d %d \n", i, j); 141 for(int s = 1; s <= top; s++) { 142 if(!f[flag][s]) { 143 continue; 144 } 145 unzip(s, now); 146 // f[i][j][s] -> f[i][j + 1][?] 147 /// now[j] now[j + 1] 148 // DP 149 LL c = f[flag][s]; 150 //printf(" > > s :"); out(); printf(" %d \n", c); 151 if(G[i][j]) { 152 if(!now[j] && !now[j + 1]) { 153 add(f[flag ^ 1][s], c); 154 } 155 continue; 156 } 157 if(!now[j] && !now[j + 1]) { /// 0 0 158 now[j] = 1; 159 now[j + 1] = 2; 160 add(f[flag ^ 1][zip(now)], c); 161 now[j] = now[j + 1] = 0; 162 } 163 else if(!now[j] || !now[j + 1]) { /// [0 1/2] [1/2 0] hold / swap 164 add(f[flag ^ 1][s], c); 165 std::swap(now[j], now[j + 1]); 166 add(f[flag ^ 1][zip(now)], c); 167 std::swap(now[j], now[j + 1]); 168 } 169 else if(now[j] == 1 && now[j + 1] == 1) { /// 1 1 the first 2 -> 1 170 int p = get2(j + 2); 171 now[p] = 1; now[j] = now[j + 1] = 0; 172 add(f[flag ^ 1][zip(now)], c); 173 now[p] = 2; now[j] = now[j + 1] = 1; 174 } 175 else if(now[j] == 2 && now[j + 1] == 2) { /// 2 2 the first 1 -> 2 176 int p = get1(j - 1); 177 now[p] = 2; now[j] = now[j + 1] = 0; 178 add(f[flag ^ 1][zip(now)], c); 179 now[1] = 1; now[j] = now[j + 1] = 2; 180 } 181 else if(now[j] == 2 && now[j + 1] == 1) { /// 2 1 merge 182 now[j] = now[j + 1] = 0; 183 add(f[flag ^ 1][zip(now)], c); 184 now[j] = 2; now[j + 1] = 1; 185 } 186 else if(i == last_x && j == last_y) { /// 1 2 END 187 bool t = 0; 188 for(int q = 0; q < j; q++) { 189 if(now[q]) { 190 t = 1; 191 break; 192 } 193 } 194 for(int q = j + 2; q <= m; q++) { 195 if(now[q]) { 196 t = 1; 197 break; 198 } 199 } 200 if(!t) add(ans, c); 201 } 202 } 203 } 204 if(i < n - 1) { 205 // change row 206 for(int s = top; s >= 1; s--) { 207 if(state[s] % 3) { 208 f[flag ^ 1][s] = 0; 209 } 210 else { 211 f[flag ^ 1][s] = f[flag ^ 1][id[state[s] / 3]]; 212 } 213 } 214 } 215 } 216 217 printf("%lld\n", ans); 218 return 0; 219 }