暑假考试题2:Nim游戏 改(博弈论)
Posted mowanying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假考试题2:Nim游戏 改(博弈论)相关的知识,希望对你有一定的参考价值。
题目:
其实就是在nim游戏基础上添加了一次可以不取的机会。
多堆石子可以看成多个游戏,它们起点的sg值异或起来就是整个游戏的sg值,若sg值为1,则先手必胜,为0,则后手必胜。
关键在于怎么求sg值:可以打表找规律->对游戏局面进行动态dfs连边,再dfs一遍求sg值(也就是求mex值)
细节:dfs能跑到的范围很小,最多到20(可能还达不到,因为边实在是太多了),所以死循环时不要怀疑是自己打错了,还可能是石子数太大了。
规律:石子数为奇数,mex值为a[i]+1,偶数,mex值为a[i]-1。
打表代码:
#include<bits/stdc++.h> using namespace std; #define N 25 #define M 100005 int tong[M][N],mexx[M],head[M],to[M],nex[M],tot=0,val[M],ndnum,fl[M]; void add(int a,int b) to[++tot]=b; nex[tot]=head[a]; head[a]=tot; void dfs(int u) if(val[u]==0) return ; if(fl[u]==0) val[++ndnum]=val[u]; add(u,ndnum); fl[ndnum]=1; dfs(ndnum); for(int i=0;i<=val[u]-1;i++) val[++ndnum]=i; add(u,ndnum); fl[ndnum]=fl[u]; dfs(ndnum); void SG(int u) if(val[u]==0) mexx[u]=0; return ; for(int i=head[u];i;i=nex[i]) int v=to[i]; SG(v); tong[u][mexx[v]]=true; for(int i=0;i<=20;i++) if(!tong[u][i]) mexx[u]=i; return ; int main() for(int i=1;i<=10;i++) int id=++ndnum; val[id]=i; fl[id]=0; dfs(id); SG(id); printf("mex:%d %d\\n",i,mexx[id]);
打表找到规律后的代码:
#include<bits/stdc++.h> using namespace std; #define ll long long int main() freopen("nim.in","r",stdin); freopen("nim.out","w",stdout); int T,n,a; scanf("%d",&T); while(T--) scanf("%d",&n); scanf("%d",&a); if(a&1) a++; else a--; ll ans=a; for(int i=2;i<=n;i++) scanf("%d",&a); if(a&1) a++; else a--; ans^=a; if(ans) printf("A\\n"); else printf("B\\n"); /* 2 2 1 2 2 2 2 */
以上是关于暑假考试题2:Nim游戏 改(博弈论)的主要内容,如果未能解决你的问题,请参考以下文章