【题目链接】
【思路要点】
- 基于连通性的的动态规划。
- 时间复杂度\(O(3^{Min\{R,C\}}*R*C)\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 105 #define HASH 1000005 #define P 100003 #define Q 20110520 struct Hash_Table { int head[P], nxt[HASH]; int curr[HASH], size, 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; value[i] %= Q; 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], finalans; void Extend(int x, int y, int curr, int dest, int 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 (tmpx || tmpy) return; if (y != m) ans[dest].modify(curr, val); else ans[dest].modify(curr << 2, val); return; } if (x == ex && y == ey) { int tcurr = curr ^ tmpx ^ tmpy; if (typex + typey == 2 && tcurr == 0) finalans = (finalans + val) % Q; return; } if (tmpy == 0 && tmpx == 0) { if (y == m) { ans[dest].modify((curr | (1 << 2 * (y - 1))) << 2, val); return; } ans[dest].modify(curr | (1 << 2 * (y - 1)), val); ans[dest].modify(curr | (1 << 2 * y), val); ans[dest].modify(curr | (2 << 2 * (y - 1)) | (2 << 2 * y), val); return; } if (tmpy != 0 && tmpx != 0) { if (typex != 1 || typey != 1) return; if (y == m) ans[dest].modify((curr ^ tmpx ^ tmpy) << 2, val); else ans[dest].modify(curr ^ tmpx ^ tmpy, val); return; } if (tmpy == 0) { int tcurr = curr ^ tmpx; if (typex == 1) { if (y == m) ans[dest].modify((tcurr | (2 << 2 * (y - 1))) << 2, val); else ans[dest].modify(tcurr | (2 << 2 * (y - 1)), val); if (y != m) ans[dest].modify(tcurr | (1 << 2 * y), val); } else { if (y == m) ans[dest].modify(tcurr << 2, val); else ans[dest].modify(tcurr, val); if (y != m) ans[dest].modify(tcurr | (2 << 2 * y), val); } return; } else { int tcurr = curr ^ tmpy; if (typey == 1) { if (y == m) ans[dest].modify((tcurr | (1 << 2 * (y - 1))) << 2, val); else ans[dest].modify(tcurr | (1 << 2 * (y - 1)), val); if (y != m) ans[dest].modify(tcurr | (2 << 2 * y), val); } else { if (y == m) ans[dest].modify(tcurr << 2, val); else ans[dest].modify(tcurr, val); if (y == m) ans[dest].modify((tcurr | (2 << 2 * (y - 1))) << 2, val); else ans[dest].modify(tcurr | (2 << 2 * (y - 1)), val); } return; } } 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; if (m > n) { swap(n, m); for (int j = 1; j <= m; j++) { scanf("\n"); for (int i = 1; i <= n; i++) scanf("%c", &mp[i][j]); } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (mp[i][j] == '_') ex = i, ey = j; } else { 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; } } } for (int i = 1; i <= m + 1; i++) num[i] = num[i - 1] << 2; 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("%d\n", finalans); } return 0; }