【题目链接】
【思路要点】
- 基于连通性的的动态规划模板题。
- 时间复杂度\(O(3^M*N*M)\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 30 #define TMPN 15 #define HASH 1000005 #define P 100003 struct Hash_Table { int head[P], nxt[HASH]; int curr[HASH], size; long long value[HASH]; void clear() { size = 0; memset(head, 0, sizeof(head)); } void modify(int x, long long val) { int pos = x % P; for (int i = head[pos]; i; i = nxt[i]) if (curr[i] == x) { value[i] += val; return; } size++; curr[size] = x; value[size] = val; nxt[size] = head[pos]; head[pos] = size; } }; Hash_Table ans[2]; char mp[MAXN][MAXN]; int n, m, ex, ey, num[MAXN], bit[MAXN], all; long long finalans; void Extend(int x, int y, int curr, int dest, long long val) { int tmpy = num[y] & curr; int tmpx = num[y - 1] & curr; int typey = 0, typex = 0; if (tmpy) { if (tmpy & (1 << 2 * y)) typey = 1; else typey = 2; } if (tmpx) { if (tmpx & (1 << 2 * (y - 1))) typex = 1; else typex = 2; } if (mp[x][y] == '*') { if (tmpy || tmpx) return; else if (y == m) { ans[dest].modify(curr << 2, val); return; } else { ans[dest].modify(curr, val); return; } } if (x == ex && y == ey) { int tcurr = curr ^ tmpy ^ tmpx; if (tcurr == 0 && typex == 1 && typey == 2) finalans += val; return; } if (tmpy == 0 && tmpx == 0) { if (y == m) return; else { ans[dest].modify(curr | (1 << 2 * (y - 1)) | (2 << 2 * y), val); return; } } if (tmpy != 0 && tmpx != 0) { int tcurr = curr ^ tmpx ^ tmpy; if (typex == 1 && typey == 2) return; if (typex == 2 && typey == 1) { if (y != m) { ans[dest].modify(tcurr, val); return; } else { ans[dest].modify(tcurr << 2, val); return; } } static int type[MAXN], q[MAXN], tnp[MAXN], pir[MAXN]; int top = 0; for (int i = 0; i <= m; i++) { tnp[i] = curr & num[i]; type[i] = 0; if (tnp[i]) { if (tnp[i] & (1 << 2 * i)) type[i] = 1; else type[i] = 2; } } for (int i = 0; i <= m; i++) { if (type[i] == 1) q[++top] = i; if (type[i] == 2) { pir[q[top]] = i; pir[i] = q[top]; top--; } } if (typex == 1 && typey == 1) { ans[dest].modify(tcurr ^ tnp[pir[y]] ^ (1 << 2 * pir[y]), val); return; } else { if (y != m) { ans[dest].modify(tcurr ^ tnp[pir[y - 1]] ^ (2 << 2 * pir[y - 1]), val); return; } else { ans[dest].modify((tcurr ^ tnp[pir[y - 1]] ^ (2 << 2 * pir[y - 1])) << 2, val); return; } } } if (tmpy == 0) { int tcurr = curr ^ tmpx; if (y != m) ans[dest].modify(curr, val); else ans[dest].modify(curr << 2, val); if (y != m) ans[dest].modify(tcurr | (typex << 2 * y), val); } else { int tcurr = curr ^ tmpy; if (y != m) ans[dest].modify(curr, val); if (y != m) ans[dest].modify(tcurr | (typey << 2 * (y - 1)), val); else ans[dest].modify((tcurr | (typey << 2 * (y - 1))) << 2, val); } } void work(int x, int y, int now) { int tx = x, ty = y + 1; if (ty > m) ty = 1, tx++; ans[now ^ 1].clear(); for (int i = 1; i <= ans[now].size; i++) Extend(x, y, ans[now].curr[i], now ^ 1, ans[now].value[i]); if (x == ex && y == ey) return; else work(tx, ty, now ^ 1); } int main() { scanf("%d%d", &n, &m); num[0] = 3; bit[0] = 1; for (int i = 1; i <= m + 1; i++) num[i] = num[i - 1] << 2; for (int i = 1; i < MAXN; i++) bit[i] = bit[i - 1] << 1; for (int i = 1; i <= n; i++) { scanf("\n"); for (int j = 1; j <= m; j++) { scanf("%c", &mp[i][j]); if (mp[i][j] == '.') ex = i, ey = j; } } if (ex == 0) printf("0\n"); else { ans[0].clear(); ans[1].clear(); ans[0].modify(0, 1); finalans = 0; work(1, 1, 0); printf("%lld\n", finalans); } return 0; }