LightOJ - 1229 Treblecross sg函数

传送门:Treblecross LightOJ - 1229 

题意:一排n个位置,有些位置已经放上了字母X,剩下的是空的。两人轮流放置X在空的位置。放置后出现连续3个X的赢。问先手是否有必胜策略?若有,可以放在哪些地方?

思路:肯定是要枚举先手放的位置,然后判断是否能赢,而判断是否能赢我们就要求sg函数了,然而这个题直接求sg函数的话很难求,因为状态太复杂了,巧妙的思路是将连续的空闲位置拿出来,看成一个独立的nim游戏,求在这些空闲位置上放X的sg值,然后求nim和(异或)就是总状态的sg值了。

详细分析:点击打开链接

代码:

#include<bits/stdc++.h>
#define ll long long
#define pi acos(-1)
#define MAXN 210
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>P;
char str[MAXN];
int len, cnt;
int ans[MAXN], sg[MAXN];
bool check()
{
	for(int i = 0; i < len - 2; i++)
	if(str[i] == 'X' && str[i + 1] == 'X' && str[i + 2] == 'X')
	return 1;
	return 0;
}
int get_sg(int n)
{
	if(sg[n] != -1) return sg[n];
	bool vis[MAXN];
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= n; i++)
	vis[get_sg(max(i - 3, 0)) ^ get_sg(max(n - i - 2, 0))] = 1;
	for(int i = 0; i < MAXN; i++)
	if(!vis[i])
	return sg[n] = i;
}
bool judge()
{
	for(int i = 0; i < len; i++)
	{
		if(str[i] == '.')
		{
			str[i] = 'X';
			if(check()) 
			{
				str[i] = '.';
				return 0;
			}
			str[i] = '.';
		}
	}
	int num = 0, ans = 0;
	for(int i = 0; i < len; i++)
	{
		if(str[i] == 'X' || (i > 0 && str[i - 1] == 'X') || (i > 1 && str[i - 2] == 'X') || (i + 1 < len && str[i + 1] == 'X') || (i + 2 < len && str[i + 2] == 'X'))
		{
			ans ^= get_sg(num);
			num = 0;
		}
		else
		num++;
	}
	ans ^= get_sg(num);
	return !ans;
}
void solve()
{
	cnt = 0;
	for(int i = 0; i < len; i++)
	{
		if(str[i] == '.')
		{
			str[i] = 'X';
			if(check() || judge())
			ans[cnt++] = i + 1;
			str[i] = '.';
		}
	}
}
int main()
{
	int T;
	cin >> T;
	int kase = 1;
	while(T--)
	{
		memset(sg, -1, sizeof(sg));
		sg[0] = 0;
		scanf(" %s", str);
		len = strlen(str);
		solve();
		printf("Case %d:", kase++);
		if(cnt == 0) printf(" 0");
		else
		for(int i = 0; i < cnt; i++)
		printf(" %d", ans[i]);
		puts("");
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值