ZOJ 3666 Alice and Bob (SG博弈)

题目:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3666

 

题意:

给一个有向图,然后A和B轮流移动棋子,棋子在每一个位置可以重叠,当某人不能走时,输!

问A和B谁赢

 

方法:

显然每一局游戏都是独立的,对每一局游戏异或即可

每一局游戏的结果可以用SG求,记忆化搜索之

 1 int dfs(int x)
 2 {
 3     if (sg[x] != -1) return sg[x];
 4     bool vis[maxn];
 5     memset(vis, 0, sizeof(vis));
 6     for (int i = head[x]; ~i; i = edge[i].next)
 7         vis[dfs(edge[i].v)] = 1;
 8     for (int i = 0;; i++)
 9         if (!vis[i]) return sg[x] = i;
10 }

 

代码:

  1 /********************************************
  2 *ACM Solutions
  3 *
  4 *@Title: ZOJ 3666 Alice and Bob
  5 *@Version: 1.0
  6 *@Time: 2014-08-26
  7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
  8 *
  9 *@Author: xysmlx(Lingxiao Ma)
 10 *@Blog: http://www.cnblogs.com/xysmlx
 11 *@EMail: xysmlx@163.com
 12 *
 13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
 14 ********************************************/
 15 // #pragma comment(linker, "/STACK:102400000,102400000")
 16 #include <cstdio>
 17 #include <iostream>
 18 #include <cstring>
 19 #include <string>
 20 #include <cmath>
 21 #include <set>
 22 #include <list>
 23 #include <map>
 24 #include <iterator>
 25 #include <cstdlib>
 26 #include <vector>
 27 #include <queue>
 28 #include <stack>
 29 #include <algorithm>
 30 #include <functional>
 31 using namespace std;
 32 typedef long long LL;
 33 #define pb push_back
 34 #define ROUND(x) round(x)
 35 #define FLOOR(x) floor(x)
 36 #define CEIL(x) ceil(x)
 37 const int maxn = 10010;
 38 const int maxm = 2000010;
 39 const int inf = 0x3f3f3f3f;
 40 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
 41 const double INF = 1e30;
 42 const double eps = 1e-6;
 43 const int P[4] = {0, 0, -1, 1};
 44 const int Q[4] = {1, -1, 0, 0};
 45 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
 46 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
 47 struct Edge
 48 {
 49     int u, v;
 50     int next;
 51     Edge(int _u = 0, int _v = 0, int _next = 0): u(_u), v(_v), next(_next) {}
 52 } edge[maxm];
 53 int head[maxn];
 54 int en;
 55 void addse(int u, int v)
 56 {
 57     edge[en] = Edge(u, v, head[u]);
 58     head[u] = en++;
 59 }
 60 int sg[maxn];
 61 int n;
 62 int kase;
 63 void init()
 64 {
 65     kase++;
 66     memset(head, -1, sizeof(head));
 67     en = 0;
 68     memset(sg, -1, sizeof(sg));
 69 }
 70 void input()
 71 {
 72     for (int i = 1; i < n; i++)
 73     {
 74         int w;
 75         scanf("%d", &w);
 76         while (w--)
 77         {
 78             int x;
 79             scanf("%d", &x);
 80             addse(i, x);
 81         }
 82     }
 83 }
 84 void debug()
 85 {
 86     //
 87 }
 88 int dfs(int x)
 89 {
 90     if (sg[x] != -1) return sg[x];
 91     bool vis[maxn];
 92     memset(vis, 0, sizeof(vis));
 93     for (int i = head[x]; ~i; i = edge[i].next)
 94         vis[dfs(edge[i].v)] = 1;
 95     for (int i = 0;; i++)
 96         if (!vis[i]) return sg[x] = i;
 97 }
 98 void solve()
 99 {
100     printf("Case %d:\n", kase);
101     int ret = 0;
102     int q;
103     scanf("%d", &q);
104     while (q--)
105     {
106         int w;
107         ret = 0;
108         scanf("%d", &w);
109         while (w--)
110         {
111             int x;
112             scanf("%d", &x);
113             ret ^= dfs(x);
114         }
115         if (ret) puts("Alice");
116         else puts("Bob");
117     }
118 }
119 void output()
120 {
121     //
122 }
123 int main()
124 {
125     // int size = 256 << 20; // 256MB
126     // char *p = (char *)malloc(size) + size;
127     // __asm__("movl %0, %%esp\n" :: "r"(p));
128 
129     // std::ios_base::sync_with_stdio(false);
130 #ifdef xysmlx
131     freopen("in.cpp", "r", stdin);
132 #endif
133 
134     kase = 0;
135     while (~scanf("%d", &n))
136     {
137         init();
138         input();
139         solve();
140         output();
141     }
142     return 0;
143 }
ZOJ 3666

 

转载于:https://www.cnblogs.com/xysmlx/p/3938329.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值