2014 Super Training #6 A Alice and Bob --SG函数
原题: ZOJ 3666 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3666
博弈问题。
题意:给你1~N个位置,N是最终点,1~N-1中某些格子能够移石头到另外一些指定的格子,1~N-1上有M个石头,位置不定,现在Alice和Bob要把这些石头全部移到N点,谁不能移则输,问先手必胜还是后手必胜。
做法:求出每个位置的SG函数值,然后将放石头的M个位置的SG函数值做异或,异或为0则Alice赢。这里讲坐标反转,1~N换成N-1~0,0点作为终点,更加直观。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std; #define N 10007 int flag[N],step[N]; int sg[N]; vector<int> v[10003]; int mex(int x) { int i,ans = 0; memset(flag,0,sizeof(flag)); for(i=0;i<v[x].size();i++) flag[sg[v[x][i]]] = 1; for(i=0;;i++) if(!flag[i]) return i; } void setSG() { int i; sg[0] = 0; for(i=1;i<=10002;i++) sg[i] = mex(i); } int main() { int n,i,j,m,q,c,x,k; int cs = 1; while(scanf("%d",&n)!=EOF) { printf("Case %d:\n",cs++); for(i=0;i<10002;i++) v[i].clear(); for(i=0;i<n-1;i++) { scanf("%d",&c); for(j=0;j<c;j++) { scanf("%d",&x); v[n-i-1].push_back(n-x); } } setSG(); int res; scanf("%d",&q); while(q--) { scanf("%d",&m); res = 0; while(m--) { scanf("%d",&k); res ^= sg[n-k]; } if(res) puts("Alice"); else puts("Bob"); } } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com