• sg函数与博弈论2


    参考链接:

    http://blog.sina.com.cn/s/blog_51cea4040100h3l9.html

    这篇主要就是讲anti-sg、multi-sg和every-sg的。

    例1 poj3537

    有一个长度为n的一维棋盘,两人轮流下子,如果一个人下了连在一起的三个子就立刻赢了,如果一个人下不了子了他就输了。3<=n<=2000

    我们可以发现,如果我们在第i个地方落子,游戏就被分解为了两个子游戏:长度为i-3和n-i-2的两个子游戏。(至于为什么我也不好解释啊,就是如果之后都在这些地方下那么肯定i位置不会连成3子)

    这样分解游戏的模型叫做multi-sg,它的sg函数定义是没什么区别的,可以直接刚。

    2000的话平方裸搜就可以了。

    //By zzq
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int sg[2333];
    int tmd=0;
    int gsg(int n)
    {
        if(n<0) return 0;
        if(sg[n]>=0) return sg[n];
        bool ff[2001]={};
        for(int i=1;i<=n;i++) ff[gsg(i-3)^gsg(n-i-2)]=1;
        for(int i=0;;i++)
        {
            if(!ff[i]) return sg[n]=i;
        }
    }
    int main()
    {
        memset(sg,-1,sizeof(sg));
        int n;
        scanf("%d",&n);
        if(gsg(n)) puts("1");
        else puts("2");
    }

    例2 bzoj1022

    nim游戏,取到最后一粒石子的人输。

    多组数据,n<=5000。

    这个东西我们可以发现除了取到最后一粒石子的人输以外都是沙茶sg,所以我们就叫它anti-sg。

    接下来就是结论啦,贾志豪神犇发明了一个sj定理可以解决这个问题:

    对于任意一个anti-sg游戏,先手必胜当且仅当:

    游戏的sg函数不为0且游戏中某个单一游戏的sg函数大于1;

    游戏的sg函数为0且游戏中没有单一游戏的sg函数大于1。

    这种结论题就直接做就是了。

    //By zzq
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int T,n;
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            bool dy1=0;
            int ans=0;
            for(int i=1;i<=n;i++)
            {
                int x; scanf("%d",&x);
                ans^=x; dy1|=x>1;
            }
            if(((bool)ans)==dy1) puts("John"); else puts("Brother");
        }
    }

    every-sg没什么靠谱的例题啊...待补

  • 相关阅读:
    POJ 1201 Intervals 差分约束
    netframework2.0,asp.net2.0,vs.net 2005
    学习.net第一天
    VS.NET 2003 控件命名规范
    .Net生成共享程序集
    汉字的编码
    [转]用C#实现连接池
    SQL表自连接用法
    一道很好玩的OOP面试题,今天比较有空,所有做了一下
    C#编程规范(2008年4月新版)
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5585224.html
Copyright © 2020-2023  润新知