POJ2425 A Chess Game(SG函数+记忆化深搜)

题目链接:传送门

题目大意:

  在一个有N个点的拓扑图上(拓扑图以邻接表的形式输入),放M个棋子(棋子与棋子之间无关,可以重合)。

  两人轮流移动棋子,每次只能移动一个棋子经过一条边。

  问先手是否必胜。

思路:

  因为图是确定的,而且是拓扑图,直接沿着边跑记忆化dfs求每个点的SG值就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>

using namespace std;
const int MAX_N = 1005;

int N, M;
int Edge[MAX_N][MAX_N];
int SG[MAX_N];

int dfs(int u)
{
    if (SG[u] >= 0)
        return SG[u];
    bool vis[MAX_N];
    memset(vis, false, sizeof vis);
    for (int i = 1; i <= Edge[u][0]; i++) {
        int v = Edge[u][i];
        int x = dfs(v);
        vis[x] = true;
    }
    int g = 0;
    while (vis[g])
        g++;
    return SG[u] = g;
}

int main()
{
    while (~scanf("%d", &N)) {
        for (int i = 0; i < N; i++) {
            SG[i] = -1;
            scanf("%d", &Edge[i][0]);
            for (int j = 1; j <= Edge[i][0]; j++) {
                scanf("%d", &Edge[i][j]);
            }
        }
        for (int i = 0; i < N; i++)
            dfs(i);

        while (~scanf("%d", &M)) {
            if (M == 0)
                break;
            int ans = 0;
            while (M--) {
                int cur;
                scanf("%d", &cur);
                ans ^= SG[cur];
            }
            if (ans)
                puts("WIN");
            else
                puts("LOSE");
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9801234.html