Treblecross UVA10561

SG定理的应用,SG[n]表示长度为n的空棋盘的mex值,可以根据第一个棋子的位置将棋盘分割,从较小的棋盘中递推得出,预处理出<=200的状态,然后根据题目所给的初始状态,会有一些地方预处理出来,然后把被分割的棋盘分别看做子游戏,利用SG定理求出函数值即可,要说明的是此题要求输出所有必胜策略的第一步输出,并不是把整个策略输出

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;

const int MAXN(210);
char str[MAXN];
bool can[MAXN], tcan[MAXN];
int SG[MAXN];
bool vis[MAXN];

int get_ans(bool *arr, int len)
{
	int ret = 0, count = 0;
	for(int i = 1; i <= len; ++i)
		if(arr[i])
		{
			++count;	
		}
		else
		{
			ret ^= SG[count];
			count = 0;
		}
	ret ^= SG[count];
	return ret;
}

int main()
{

	int T;
	scanf("%d", &T);
	SG[0] = 0;
	SG[1] = 1;
	SG[2] = 1;
	SG[3] = 1;
	for(int i = 4; i <= 200; ++i)
	{
		memset(vis, 0, sizeof(vis));
		for(int j = 3; j <= 5 && i-j >= 0; ++j)
			vis[SG[i-j]] = true;
		for(int j = 6; i-j >= 0; ++j)
			vis[SG[j-5]^SG[i-j]] = true;
		for(int j = 0; j <= 200; ++j)
			if(!vis[j])
			{
				SG[i] = j;
				break;
			}
	}
	while(T--)
	{
		scanf("%s", str+1);
		int len = strlen(str+1);
		bool flag = false;
		for(int i = 1; i <= len; ++i)
		{
			if(i > 2 && str[i-2] == 'X' && str[i-1] == 'X')
			{
				if(flag)
					putchar(' ');
				else
					printf("WINNING\n");
				printf("%d", i);
				flag = true;
				continue;
			}
			if(i > 1 && i < len && str[i-1] == 'X' && str[i+1] == 'X')
			{
				if(flag)
					putchar(' ');
				else
					printf("WINNING\n");
				printf("%d", i);
				flag = true;
				continue;
			}
			if(i < len-1 && str[i+1] == 'X' && str[i+2] == 'X')
			{
				if(flag)
					putchar(' ');
				else
					printf("WINNING\n");
				printf("%d", i);
				flag = true;
				continue;
			}
		}
		if(flag)
			putchar('\n');
		else
		{
			memset(can, -1, sizeof(can));
			for(int i = 1; i <= len; ++i)
				if(str[i] == 'X')
				{
					for(int j = i-2; j <= i+2; ++j)
						if(j >= 1 && j <= len)
							can[j] = false;
				}
			int ans = get_ans(can, len);
			if(ans != 0)
			{
				printf("WINNING\n");
				bool print_space = false;
				for(int i = 1; i <= len; ++i)
					if(can[i])
					{
						memcpy(tcan, can, sizeof(tcan));
						for(int j = i-2; j <= i+2; ++j)
							if(j >= 1 && j <= len)
								tcan[j] = false;
						int tans = get_ans(tcan, len);
						if(tans == 0)
						{
							if(print_space)
								putchar(' ');
							printf("%d", i);
							print_space = true;
						}
					}
				printf("\n");
			}
			else
				printf("LOSING\n\n");
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值