码迷,mamicode.com
首页 > 其他好文 > 详细

SG函数

时间:2018-12-01 01:14:43      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:ima   ret   初始化   分享   元素   棋盘   方向   状态   初始   

SG函数

一种用于确定一个博弈是否有必胜方法的函数

必胜点(P):在这一点,若双方都采取最优操作,必胜。 必败点(N)同理。

  • 注:若一个点存在一个操作(道路)可以达到比必败点,则这个点是必胜点,否则是必败点。

    核心:从最终结果逆推。

    举个栗子:。
    一个N*M棋盘,一个棋子放在右上角,只能往←、↙,↓三个方向走。两人轮流移动棋子,首先移到左下角的获胜。 请问:当N、M满足什么条件时先手必胜?

    技术分享图片
    如图,由必胜点和必败点的关系可无限拓展。

SG函数

  • SG(x)=mex{SG(xi)},xi为x的(多个)后续状态
    mex函数:mex{x1,x2,……xn}表示不在集合中且最小的非负整数。如mex{1,2,5}=0,记mex{}=0.

举例:
有n个石子,一次只能取出1、3、4个,两人轮流取,首先取完石子的获胜

技术分享图片
如图,同上,若一个点存在一个操作(道路)可以达到比必败点,则这个点是必胜点,否则是必败点。直观的,若SG大于0,则为必胜点。

代码实现:

int cmd[n]; //每个元素代表一个操作
int SG[a];   
int mex[b]; //用于标记mex函数中已经出现的整数

int *sg()  
{
    menset(SG,0,sizeof(SG));  
    int i,j;  
    for(i=1;i<a;i++)  //从1开始因为SG[0]=0
    {  
        menset(mex,0,sizeof(mex)); //每次都要初始化标记
        for(j=0;j<n&&cmd[j]<=i;j++)
        {
            mex[SG[ i-cmd[j] ]=1; //标记
        }
        for(i=0;i<b;i++)
        {
            if(!mex[i]) //找到第一个不被标记(未出现)的的整数i
                SG[i]=i;
        }
    }
   return SG;
}

SG函数

标签:ima   ret   初始化   分享   元素   棋盘   方向   状态   初始   

原文地址:https://www.cnblogs.com/Bz1092467670/p/10047931.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!