暑假考试题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游戏 改(博弈论)的主要内容,如果未能解决你的问题,请参考以下文章

博弈论

[2016北京集训试题6]魔法游戏-[博弈论-sg函数]

Nim游戏 模板+拓展 博弈论+sg函数

博弈论Nim游戏:台阶集合拆分(AcWing)

博弈论(基础概念+例题)

292. Nim 游戏博弈论