uva1378

来源:互联网 发布:电脑运行命令网络连接 编辑:程序博客网 时间:2024/05/29 23:23

sg函数的本质就是把游戏转化成nim博弈,其他就很简单了。。直接看论文就好了

王的论文里提到的take&break问题在挑战上有,此题其实也就是一个take&break问题,i位置上的石头的数目是(n-1-i)然后可以变成(n-1-j)和(n-1-k)求这两个局面的异或然后就可以搞sg了其他很简单的吧。。。

关键是把张一飞的论文搞懂就明白了,那是这题的理论基础。2002年 张一飞:透析一类搏弈游戏的解答过程,acdream群里也有论文


#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int n, s[200], sg[100];bool temp[100000];int stackk[100000], top = -1;void init(){for (int i = 0; i <= 23; i++){for (int j = 0; j < i; j++)for (int k = j; k < i; k++){temp[sg[j] ^ sg[k]] = 1;}int q = 0;while (temp[q])q++;sg[i] = q;for (int i = 0; i < 1000; i++)temp[i] = 0;}}int main(){int t;int k = 1;init();while (scanf("%d", &n)&&n){int ans = 0;for (int i = 0; i < n; i++){scanf("%d", &s[i]);if (s[i] & 1)ans ^= sg[n - 1 - i];}if (ans == 0){printf("Game %d: -1 -1 -1\n", k++);}else{int ans1 = -1, ans2 = -1, ans3 = -1;for (int i = 0; i < n; i++){if (s[i] == 0)continue;if (ans1 != -1)break;for (int j = i + 1; j < n; j++){if (ans1 != -1)break;for (int k = j; k < n; k++){if (ans1 != -1)break;if ((ans^sg[n - 1 - i] ^ sg[n - 1 - j] ^ sg[n - 1 - k])==0)ans1 = i, ans2 = j, ans3 = k;}}}printf("Game %d: %d %d %d\n", k++, ans1, ans2, ans3);}}return 0;}



原创粉丝点击