【SG函式 && 存在不可達狀態】Gym
阿新 • • 發佈:2018-12-24
Step1 Problem:
一個 100*100 的棋盤,棋盤上有 n 個棋子,Alice 和 Bob 輪流進行操作。
操作:選擇棋盤上的一枚棋子 ,移動至 , 同時不能出界。
誰先把第一個棋子移動至 (0, 0) 的誰獲勝。
問先手能否獲勝。
Step2 Ideas:
第一點: 沒有人會傻到把棋子移動到第一行,或者第一列,或者 行列 相等的位置。( 除了 (0, 0) )。
所以我們把這些位置設為不可到達的位置。
所以當所有棋子都到達 (1, 2) 或者 (2, 1) 後獲勝。
問題就變成了一個簡單的求 sg 的博弈。
Step3 Code:
#include<bits/stdc++.h> using namespace std; int sg[105][105]; void init() { memset(sg, 0, sizeof(sg)); for(int i = 1; i <= 100; i++) { for(int j = 1; j <= 100; j++) { if(i==j) continue; int mex[10005] = {0}; for(int u = 1; u <= max(i, j); u++) { if(u < i && i-u!=j) { mex[sg[i-u][j]]++; } if(u < j && j-u!=i) { mex[sg[i][j-u]]++; } if(u < i && u < j) { mex[sg[i-u][j-u]]++; } while(mex[sg[i][j]]) sg[i][j]++; } } } } int main() { init(); int n; scanf("%d", &n); int flag = 0, ans = 0; int x, y; for(int i = 1; i <= n; i++) { scanf("%d %d", &x, &y); if(x==y) { flag = 1; } else if(x==0 || y==0) flag = 1; else ans ^= sg[x][y]; } if(flag) printf("Y\n"); else { if(ans) printf("Y\n"); else printf("N\n"); } return 0; }