[賽記] 衝刺CSP聯訓模擬1[衡中]

Peppa_Even_Pig發表於2024-10-05

幾何 100pts

賽時打的 $ DP $ 沒有用 bitset 最佳化過了,也是放過了暴力

考慮設狀態 $ f_{i, j, k} $ 表示考慮到第 $ i $ 位,到第 $ j $ 位 $ x $ 和第 $ k $ 位 $ y $ 可不可取,直接轉移即可;

時間複雜度:$ \Theta(|s||x||y|) $,應該是過不了的;

點選檢視暴力
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t;
char s[500005], x[55], y[55];
int sl, xl, yl;
bool f[2][52][52];
int main() {
	freopen("geometry.in", "r", stdin);
	freopen("geometry.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--) {
		cin >> (s + 1);
		cin >> (x + 1);
		cin >> (y + 1);
		memset(f, false, sizeof(f));
		sl = strlen(s + 1);
		xl = strlen(x + 1);
		yl = strlen(y + 1);
		f[0][xl][0] = true;
		f[0][0][yl] = true;
		for (int i = 1; i <= sl; i++) {
			memset(f[i & 1], false, sizeof(f[i & 1]));
			for (int j = 0; j <= xl; j++) {
				for (int k = 0; k <= yl; k++) {
					if (s[i] == x[j]) {
						if (j - 1 == 0) {
							f[i & 1][j][k] |= f[(i - 1) & 1][xl][k];
							f[i & 1][j][k] |= f[(i - 1) & 1][0][k];
						} else {
							f[i & 1][j][k] |= f[(i - 1) & 1][j - 1][k];
						}
					}
					if (s[i] == y[k]) {
						if (k - 1 == 0) {
							f[i & 1][j][k] |= f[(i - 1) & 1][j][0];
							f[i & 1][j][k] |= f[(i - 1) & 1][j][yl];
						} else {
							f[i & 1][j][k] |= f[(i - 1) & 1][j][k - 1];
						}
					}
				}
			}
		}
		if (f[sl & 1][xl][yl] || f[sl & 1][xl][0] || f[sl & 1][0][yl]) {
			cout << "Yes" << '\n';
		} else {
			cout << "No" << '\n';
		}
	}
	return 0;
}

根據我們以前的經驗,我們可以將答案與狀態後兩維中的一位互換,所以設 $ f_{i, j} = k $ 表示考慮前 $ i $ 位,到第 $ j $ 位 $ x $ 時所有合法的 $ y $ 的狀態,這時我們就可以用 bitset 來儲存 $ f $ 陣列,進而轉移;

轉移其實就是迴圈移位和按位與和按位或的操作;

時間複雜度:$ \Theta(\frac{|s||x||y|}{w}) $;

點選檢視程式碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <bitset>
using namespace std;
int t;
char s[500005], x[55], y[55];
int sl, xl, yl;
bitset<55> f[2][52];
bitset<55> g[500005];
bitset<55> Y(bitset<55> x) {
	int y = x[yl];
	bitset<55> bit = (x << 1);
	if (y) bit[1] = 1;
	return bit;
}
int main() {
	freopen("geometry.in", "r", stdin);
	freopen("geometry.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--) {
		cin >> (s + 1);
		cin >> (x + 1);
		cin >> (y + 1);
		memset(f, 0, sizeof(f));
		memset(g, 0, sizeof(g));
		sl = strlen(s + 1);
		xl = strlen(x + 1);
		yl = strlen(y + 1);
		for (int i = 1; i <= sl; i++) {
			for (int j = 1; j <= yl; j++) {
				if (s[i] == y[j]) g[i][j] = 1;
			}
		}
		f[0][0][0] = 1;
		for (int i = 1; i <= sl; i++) {
			memset(f[i & 1], 0, sizeof(f[i & 1]));
			for (int j = 0; j <= xl; j++) {
				if (s[i] == x[j]) {
					f[i & 1][j] |= f[(i - 1) & 1][j - 1];
					if (j - 1 == 0) f[i & 1][j] |= f[(i - 1) & 1][xl];
				}
				bitset<55> b = Y(f[(i - 1) & 1][j]);
				b &= g[i];
				f[i & 1][j] |= b;
			}
		}
		if (f[sl & 1][xl][yl] || f[sl & 1][xl][0] || f[sl & 1][0][yl]) {
			cout << "Yes" << '\n';
		} else {
			cout << "No" << '\n';
		}
	}
	return 0;
}

分析 0pts

$ DP $,。。。

點選檢視程式碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
long long a, b;
long long f[500005][2][2], w[2][2];
struct sss{
	int t, ne;
}e[2000005];
int h[2000005], cnt;
void add(int u, int v) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
}
void dfs(int x, int fa) {
	f[x][0][0] = 0;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa) continue;
		dfs(u, x);
		for (int j = 0; j <= 1; j++) {
			for (int k = 0; k <= 1; k++) {
				w[j][k] = f[x][j][k];
				f[x][j][k] = 0x3f3f3f3f3f3f3f3f;
			}
		}
		for (int j = 0; j <= 1; j++) {
			for (int k = 0; k <= 1; k++) {
				for (int uj = 0; uj <= 1; uj++) {
					for (int uk = 0; uk <= 1; uk++) {
						f[x][j][k | uj | uk] = min(f[x][j][k | uj | uk], w[j][k] + f[u][uj][uk] + a);
						long long now = 0;
						if (j && uj) {
							now = -b;
						} else if (!j && !uj) {
							now = b;
						}
						f[x][j ^ 1][k | (uj ^ 1) | uk] = min(f[x][j ^ 1][k | (uj ^ 1) | uk], w[j][k] + f[u][uj][uk] + now);
					}
				}
			}
		}
	}
}
int main() {
	freopen("analyse.in", "r", stdin);
	freopen("analyse.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	cin >> a >> b;
	a = min(a, b);
	int x, y;
	for (int i = 1; i <= n - 1; i++) {
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	memset(f, 0x3f, sizeof(f));
	dfs(1, 0);
	cout << min({f[1][0][0], f[1][0][1] - b, f[1][1][0] - b, f[1][1][1] - b});
	return 0;
}

相關文章