拍了半小时没拍出来
//#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lll __int128
#define ull unsigned long long
#define ui unsigned int
#define veci vector<int>
#define vecb vector<bool>
#define vecl vector<long long>
#define vecn vector<node>
#define quei queue<int>
#define quen queue<node>
const int N = 1 << 26, inf = 0x7FFFFFFF;
const ll INF = 0x7FFFFFFFFFFFFFFF;
struct hashe {
int mod, cnt;
struct node {
int key, v, nxt;
};
vector<int>head;
vector<node>h;
void init(int n) {
mod = n;
head.resize(n);
h.resize(1);
cnt = 0;
}
hashe(int n = 0) { init(n); }
int find(int key) {
int it, hs = key % mod;
for (it = head[hs]; it; it = h[it].nxt)
if (h[it].key == key)
return it;
return 0;
}
void make(int key, int v) {
int hs = key % mod;
h.push_back({ key,v,head[hs] });
head[hs] = ++cnt;
return;
}
void insert(int key, int v) {
int hs = key % mod;
int it = find(key);
if (it)h[it].v += v;
else make(key, v);
return;
}
int query(int key) { return h[find(key)].v; }
int size() { return cnt; }
void clear(int n) { head.clear(); h.clear(); init(n); }
};
hashe dp[2];
//ll dp[2][N];//1左括号,2右括号,0无括号
bool mp[12][12];
int n, m, ex, ey;
int p = 0;
ll ans = 0;
void print(int num) {
for (int i = m * 2; i >= 0; i -= 2)
cout << ((num >> i) & 3);
cout << '\n';
return;
}
void solve() {
dp[0].init(299987);
dp[1].init(299987);
dp[0].insert(0, 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int np = p ^ 1;
dp[np].clear(299987);
for (int g = 1; g <= dp[p].size(); g++) {
int k = dp[p].h[g].key, v = dp[p].h[g].v;
//cout << v << ' '; print(k);
int l = k & 3, u = k >> m >> m;
int nk = (k & ((1 << m << m) - 1)) >> 2 << 4;
if (j == 0 && l)continue;
if (!mp[i][j]) {
if (!l && !u)
dp[np].insert(nk, v);
//dp[np][nk] += dp[p][k];
}
else if (!l && !u)
dp[np].insert(nk ^ 6, v);
//dp[np][nk ^ 6] += dp[p][k];
else if (l && !u) {
dp[np].insert(nk ^ l, v);
dp[np].insert(nk ^ (l << 2), v);
//dp[np][nk ^ l] += dp[p][k];
//dp[np][nk ^ (l << 2)] += dp[p][k];
}
else if (!l && u) {
dp[np].insert(nk ^ u, v);
dp[np].insert(nk ^ (u << 2), v);
//dp[np][nk ^ u] += dp[p][k];
//dp[np][nk ^ (u << 2)] += dp[p][k];
}
else {
if (l == 1 && u == 1) {
int flag = 1;
for (int b = 2 * m, t = nk; t; b -= 2, t >>= 2) {
int tmp = t >> b;
if (tmp == 1)flag++;
if (tmp == 2)flag--;
if (!flag) {
dp[np].insert(nk ^ (3 << b), v);
//dp[np][nk ^ (tmp << b)] += dp[p][k];
break;
}
}
}
if (l == 2 && u == 2) {
int flag = -1;
for (int b = 4, t = nk >> 4; t; b += 2, t >>= 2) {
int tmp = t & 3;
if (tmp == 1)flag++;
if (tmp == 2)flag--;
if (!flag) {
dp[np].insert(nk ^ (3 << b), v);
//dp[np][nk ^ (tmp << b)] += dp[p][k];
break;
}
}
}
if (l == 2 && u == 1)
dp[np].insert(nk, v);
//dp[np][nk] += dp[p][k];
if (l == 1 && u == 2) {
//if (nk)dp[np].insert(nk, v);//dp[np][nk] += dp[p][k];
if (nk == 0 && i == ex && j == ey)ans += v;
}
}
}
//cout << '\n' << i + 1 << ' ' << j + 1 << '\n';
p ^= 1;
}
}
cout << ans;
return;
}
int main() {
// freopen("train.in", "r", stdin);
// freopen("train.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
char c; cin >> c;
if (c == '.')mp[i][j] = 1, ex = i, ey = j;
else mp[i][j] = 0;
}
solve();
return 0;
}
存储状态是用滚动的方式,这样子可以少掉一维,左边是前m次枚举位置的括号状态,最右边是左边的括号状态