40pts求救!!!
查看原帖
40pts求救!!!
544756
xiaobing楼主2024/10/15 21:47

拍了半小时没拍出来

//#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次枚举位置的括号状态,最右边是左边的括号状态

2024/10/15 21:47
加载中...