2018桂林J - Stone Game(博弈)

2018桂林J - Stone Game(博弈),第1张

2018桂林J - Stone Game(博弈)

传送门


题目

爱丽丝和鲍勃总是在玩游戏!今天的游戏是依次从石堆中取出石头。 有n堆石头,第I堆包含A[i]块石头。

由每堆石头的数量与其邻居的不同,他们决定在不破坏财产的情况下,一次从其中一堆石头中取出一块石头(不能在拿走一块石头后,相邻的不同石头变相同)。爱丽丝先走。 拿不到石头的玩家将输掉游戏。 你应该注意到,即使是一堆0石也还是被视为一堆!


题解

只需每次判断可以拿走多少次sum,当sum是奇数,A赢,反之B赢。

1、当a[i]都小于两边,a[i]可以变成0;

2、当a[i]都大于一边,小于一边,a[i]可以变成较小的那一边+1;

3、当a[i]都大于两边,a[i]可以变成两边最大值+1;

我们只需从头开始反复多遍历几次,就得出答案。


代码

要用scanf 和printf ,不然会被卡。

#include
#define ms(a) memset(a,0,sizeof(a));
typedef long long ll;
using namespace std;
const int N = 1e5 + 5;
 
int a[N];
int n;
ll f() {
	ll x=0;
	for (int i = 1; i <= n; i++) {
		int m = -1;
		if (a[i] > a[i - 1])m = max(m, a[i - 1]);
		if (a[i] > a[i + 1])m = max(m, a[i + 1]);
		x += a[i] - m - 1;
		a[i] = m + 1;
	}
	return x;
}
bool solve() {
	ll sum = 0;
scanf("%d", &n);
	a[0] = a[n + 1] = INT_MAX;
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	ll x;
	while (1) {
		x = f();
		sum += x;
		if (!x)break;
	}
	if (sum & 1)return 1;
	else return 0;
}
int main() {
	int t;
	cin >> t;
	for (int i = 1; i <= t; i++) {
		if (solve())printf("Case %d: Alicen", i);
		else printf("Case %d: Bobn", i);
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5503749.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-12
下一篇 2022-12-12

发表评论

登录后才能评论

评论列表(0条)

保存