hdu1524
dfs+SG函数,
游戏描述是你在一个有向图上有N棋子,你能将棋子进行移动,到棋子都移动到出度为0的顶点时就不能再移动,此时不能再移动的player就算输.
这道题是最典型的有向图游戏的博弈,方法其实在ACM中的博弈游戏综述(2)中已经进行了介绍,做DFS深搜,把所有节点的SG值都算出来,然后对每个棋子的SG值进行异或运算,得出不等0就是WIN,0和的局面就是LOSE。
//============================================================================ // Name : 1524.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; vector <int> V[1010]; int sg[1010]; int n, m, t, ans, p; int GetSG(int k){ if(sg[k] >= 0) return sg[k]; bool vis[1010]; memset(vis, 0, sizeof(vis)); for(int i = 0;i < V[k].size();i++){ if(sg[V[k][i]]!=-1) vis[sg[V[k][i]]] = true; else{ sg[V[k][i]] = GetSG(V[k][i]); vis[sg[V[k][i]]] = true; } } for(int i = 0;i < n;i++){ if(!vis[i]){ return sg[k] = i; } } return 0; } int main() { while(scanf("%d", &n)!=EOF) { for(int i = 0;i <= n;i++) sg[i] = -1; for(int i = 0;i <= n;i++){ V[i].clear(); } for(int i = 0;i < n;i++) { scanf("%d", &p); for(int j = 0;j < p;j++) { scanf("%d", &t); V[i].push_back(t); } } while(scanf("%d", &m)&&m) { ans = 0; for(int i = 0;i < m;i++) { scanf("%d", &t); if(sg[t] >= 0) ans ^= sg[t]; else ans ^= GetSG(t); } if(ans > 0) printf("WIN\n"); else printf("LOSE\n"); } } return 0; }