[COCI2021-2022#1] Kamenčići

[COCI2021-2022#1] Kamenčići

题意

有一排石头,石头有红色和蓝色。

Alice 和 Bob 轮流从两端取石头,Alice 先手。

谁先去出 \(k\) 块红色石头谁输掉,求出最后谁获胜。

思路

先考虑搜索,记录当前区间,Alice 和 Bob 的红色石头个数,回合数。

再考虑记忆化,但 \(O(n^4)\) 的空间无法承受。

发现只需要 Alice 的红色石头个数,Bob 的个数可以通过计算得出。

时/空间复杂度:\(O(n^3)\)

代码

#include <bits/stdc++.h>
using namespace std;
int n, k, s1[351], s2[351];
string S;
bool dp[351][351][351][2];
bool dfs(int l, int r, int k1, int state) {
	if (dp[l][r][k1][state]) return dp[l][r][k1][state];
	int k2 = s1[l - 1] + s2[r + 1] - k1;
	if (!state) {
		if (k1 == k) return 0;
		if (k2 == k) return 1;
		return dp[l][r][k1][state] = 
			(!dfs(l, r - 1, k1 + (S[r - 1] == 'C'), state ^ 1)
			|| !dfs(l + 1, r, k1 + (S[l - 1] == 'C'), state ^ 1));
	} else {
		if (k2 == k) return 0;
		if (k1 == k) return 1;
		return dp[l][r][k1][state] = 
			(!dfs(l, r - 1, k1, state ^ 1)
			|| !dfs(l + 1, r, k1, state ^ 1));
	}
}
int main() {
	cin >> n >> k >> S;
	for (int i = 0; i < S.size(); i ++)
		s1[i + 1] = s1[i] + (S[i] == 'C');
	reverse(S.begin(), S.end());
	for (int i = 0; i < S.size(); i ++)
		s2[i + 1] = s2[i] + (S[i] == 'C');
	reverse(S.begin(), S.end());
	reverse(s2 + 1, s2 + n + 1);
	cout << (dfs(1, n, 0, 0) ? "DA" : "NE");
	return 0;
}
posted @ 2024-09-14 08:09  maniubi  阅读(13)  评论(0)    收藏  举报