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; }