ZOJ 3666 Alice and Bob
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3666
ZOJ 2012年11月月赛的A题
看到Alice和Bob这两个名字就猜到是博弈的题目了
一个包含n(n <= 10000)个节点有向无环图上有m个可以移动的点,两名玩家轮流移动一个点,第一个不能改变移动局面的玩家输掉比赛
经典的博弈题目,整个局面的sg值为所有单个游戏g值异或的结果
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<stdlib.h> 5 #include<math.h> 6 #include<map> 7 #include<stack> 8 #include<queue> 9 #include<algorithm> 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 #define MAX(a,b) ((a)>(b)?(a):(b)) 12 #define MIN(a,b) ((a)<(b)?(a):(b)) 13 #define INF 0x3f3f3f3f 14 #pragma comment(linker, "/STACK:102400000,102400000") 15 using namespace std; 16 17 int sg[10009]; 18 int head[10009], pre[1000009], next[1000009]; 19 int cc, n; 20 21 void addedge( int a, int b ) { 22 pre[cc] = b; 23 next[cc] = head[a]; 24 head[a] = cc++; 25 } 26 27 int f( int a ) { 28 if( sg[a] != -1 ) { 29 return sg[a]; 30 } 31 int i, b; 32 int vis[10009]; 33 mem( vis, 0 ); 34 for(i = head[a]; i != -1; i = next[i] ) { 35 b = pre[i]; 36 vis[f( b )] = 1; 37 } 38 for( i = 0; ; i++ ) { 39 if( vis[i] == 0 ) { 40 return sg[a] = i; 41 } 42 } 43 } 44 45 int main() { 46 #ifndef ONLINE_JUDGE 47 freopen("E:/ACMData.txt","r",stdin); 48 #endif 49 int n, i, j, m, b, cnt; 50 int cases = 1; 51 while(~scanf("%d", &n)) { 52 mem(sg, -1); 53 mem(head, -1); 54 cc = 0; 55 for( i = 1; i < n; i++ ) { 56 scanf("%d", &m); 57 while( m-- ) { 58 scanf("%d", &b); 59 addedge(i, b); 60 } 61 } 62 scanf("%d", &m); 63 printf("Case %d:\n", cases++); 64 while( m-- ) { 65 int ret = 0; 66 scanf("%d", &cnt); 67 while( cnt-- ) { 68 scanf("%d", &b); 69 ret ^= f(b); 70 } 71 printf("%s\n", ret == 0 ? "Bob" : "Alice"); 72 } 73 } 74 return 0; 75 }
浙公网安备 33010602011771号