SG函数(博弈论)

SG函数起源于一个经典的问题如下:

给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移 动者判负。事实上,这个游戏可以认为是所有Impartial Combinatorial Games(公平组合游戏)的抽象模型。也就是说,任何一个ICG都可以通过把每个局面看成一个顶点,对每个局面和它的子局面连一条有向边来抽象成这个“有向图游戏”。下 面我们就在有向无环图的顶点上定义Sprague-Grundy(简称SG)函数。

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0,而sg(x) = mex ( sg(y) |y是x的后继结点 )。

所谓后继结点就是当前结点经过一个操作可以变成的状态。比如对于取石子游戏,假如每次可以取的数目是1,2,4,当前的石子数目也就是当前状态是5,那么5的后继结点就是{5-1, 5-2, 5-4}={4,3,1};如果5的三个后继结点的SG函数值分别为0,1,3,那么5的SG值就是集合{0,1,3}的补集的最小元素,也就是2。

关于整个游戏的sg值之和sum,定义sum=sg1 ^ sg2 ^ sg3 ^ ……sgn.  其中^表示按位异或运算。

结论:一个游戏的初始局面是必败态当且仅当sum=0。

关于SG函数的计算分三种情况:

  • 可选步数为1~m的连续整数时,直接取模即可,SG(x)=x%(m+1)
  • 可选步数为任意步时,SG(x) = x
  • 可选步数为一系列不连续的整数时,只能按部就班用getSG()函数求解。


下面给出一个SCDN上的一个具体编程例子:

石子游戏(2)

  • 发布公司:
  • 有 效 期:
  • CSDN
  • 2014-06-172015-06-17
  • 难 度 等 级:
  • 答 题 时 长:
  • 编程语言要求:
  • 120分钟
  • C C++ Java C#
题目详情

甲乙两人面对若干堆石子,其中每一堆石子的数目可以任意确定。 两人轮流按下列规则取走一些石子,游戏的规则如下: 1.每一步应取走至少一枚石子,至多取m枚石子;2.每一步只能从某一堆中取走石子; 3.如果谁无法按规则取子,谁就是输家。 如果甲乙两人都采取最优的策略,甲先拿,请问,是甲必胜还是乙必胜. 输入格式: 多组数据,每组数据两行,第一行是两个整数N和m, 2<=N<=10000 1<=m<=10000。, 下一行是N个正整数,代表每堆的石子数,石子数在32位整数内。 输出格式: 每组测试数据输出一行,如果甲存在必胜策略,输出"Win",否则输出"Lost"




答题说明

输入样例

2 3

4 4

输出样例:

Lost


AC代码如下(java):

import java.util.Scanner;

public class Main {


    public static void main(String[] args) {
        
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            
            int n = in.nextInt();
            int m = in.nextInt();
            int sum = 0;
            while(n-- > 0){
                
                long t = in.nextLong();
                sum ^= t%(m+1);
                
            }
            
            if(sum == 0){
                System.out.println("Lost");
            }else{
                System.out.println("Win");
            }
            
        }
        
        
    }

}

以上一些观点参考于其他的博文,嘿嘿~~~~~,忘大牛勿喷!!!

参考文章:http://blog.163.com/scuqifuguang@126/blog/static/171370086201101711276278/

http://www.cnblogs.com/frog112111/p/3199780.html













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值