POJ-3537 Crosses and Crosses (博弈, SG函数)

Crosses and Crosses
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 2447   Accepted: 910
Case Time Limit: 2000MS

Description

The game of Crosses and Crosses is played on the field of 1 × n cells. Two players make moves in turn. Each move the player selects any free cell on the field and puts a cross ‘×’ to it. If after the player’s move there are three crosses in a row, he wins.

You are given n. Find out who wins if both players play optimally.

Input

Input file contains one integer number n (3 ≤ n ≤ 2000).

Output

Output ‘1’ if the first player wins, or ‘2’ if the second player does.

Sample Input

3
6

Sample Output

1
2


思路:

       博弈SG函数,原本不是太难的一道题,结果浪费了很长时间,要总结下教训!

       首先 hash 数组是递归函数(getSG函数)内部的呀,千万不能设成全局变量啊啊啊,那就太二了啊啊啊!妹的,折腾了好久都没发现!

       本题思路: 首先找一下必胜态,其实必胜态即出现 “XXX” 之前的一个状态,有“XX_”,“X_X”,“XX_” 三种,所以每次先手放入一个棋子时,其左边两个位置和右边两个位置后手都不能放棋子了,否则就输了。例如,在一共n个格子的情况了,在i位置放入一个棋子,那么i前面能放棋子的格子有 i - 3个,i后边能放棋子的格子有 n - i - 2 个,所以 mg[i] = mex{ mg[i - 3] ^ mg[n - i - 2]};


代码:

#include <stdio.h>
#include <string.h>
#define N 2100

int sg[N];

int getSG(int n)
{
	if(n <= 0)
		return 0;
	if(sg[n] != -1)
		return sg[n];

    bool hash[N];           // 不能设全局,一定是在递归函数内 
	memset(hash, 0, sizeof(hash));
	for(int i = 1; i <= n / 2 + 1; i ++){
		hash[getSG(i - 3) ^ getSG(n - i - 2)] = 1;
	}

	for(int j = 0; ; j ++)
		if(hash[j] == 0)
			return sg[n] = j;
}

int main()
{
	int n;
	memset(sg, -1, sizeof(sg));
	while(scanf("%d", &n) != EOF){
		int ans = getSG(n);
		if(ans)
			printf("1\n");
		else
			printf("2\n");
	}

	return 0;
} 


你可能感兴趣的:(博弈,sg函数)