A Chess Game POJ - 2425(SG函式)
阿新 • • 發佈:2018-12-01
POJ 2425
題意:
一個有向無環圖,在若干點上有若干棋子,兩人輪流移動棋子,每次只能將一個棋子移動一步,當無棋子可移動時輸,即移動最後一枚棋子者勝;
思路:
假設只有一枚棋子,那麼對於一個點的勝負局面其實就是其SG值;
多枚棋子的勝負局面就是每個點的SG值異或和;
現在就是要求每個點的SG值;
SG(x)=mex(SG(y) | y是x的後繼點);
mex(minimal excludant)定義:這是施加於一個集合的運算,表示最小的不屬於這個集合的非負整數。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0;
SG的求解可以直接暴力求解,也可以dfs記憶化搜尋;
此題直接搜尋會超時;
#include <stdio.h> #include <string.h> #include <vector> using namespace std; vector<int> vec[1010]; int sg[1010], n; //DFS求解SG函式; int SG(int x){ int vis[1010]; if(sg[x]!=-1) return sg[x]; memset(vis, 0, sizeof(vis)); for(int i=0; i<vec[x].size(); i++){ vis[SG(vec[x][i])]=1; } for(int i=0; i<n; i++) if(!vis[i]) return sg[x]=i; } int main(){ while(~scanf("%d", &n)){ for(int i=0; i<n; i++) vec[i].clear(); int m, p; memset(sg, -1, sizeof(sg)); for(int i=0; i<n; i++){ scanf("%d", &m); for(int j=0; j<m; j++){ scanf("%d", &p); vec[i].push_back(p); } if(m==0) sg[i]=0; } for(int i=0; i<n; i++){ if(sg[i]==-1) sg[i]=SG(i); } // for(int i=0; i<n; i++){ // printf("%d: %d\n", i, sg[i]); // } while(scanf("%d", &m), m){ int pos, ans=0; for(int i=0; i<m; i++){ scanf("%d", &pos); ans^=sg[pos]; } if(ans) printf("WIN\n"); else printf("LOSE\n"); } } return 0; }