Sprague-Grundy定理解决了一个游戏。 (代码厨师ASTRGAME)

时间:2012-12-24 05:07:42

标签: game-theory

我在这里问这个,因为我没有在代码厨师论坛上得到答案。 Thread at codechef.

你好。这是我做过的第一个问题。我收到了TLE错误。

Problem - ASTRGAME.

所以我最初的方法是创建一个 Min-Max游戏树。这是我的most recent solution.

伪代码算法是:

def recursiveFunction(string, currentTurn):
        for word in dictionary: 
             if word is in string: //use a string matching algorithm
                  remove word from string, and split the remaining string
                  value-a = recursiveFunction(string-a, !currentTurn)
                  if value-a == currentTurn return currentTurn //winning position
                  value-b recursiveFunction(string-b, !currentTurn)
                  if value-b == currentTurn return currentTurn //winning position

        if none of the words in the dictionary are in the string (or none of them are winning positions)
            return !currentTurn   //losing position

(我认为这是对的)。

所以这个想法是,它是递归分支出来的,但是如果它找到一个它肯定会赢的分支,那么它可以跳过该级别的其他分支。

但是当然,我收到了一个TLE错误,所以我在这里寻找指导。

editorial建议使用Sprague-Grundy定理。 使用S-G定理进行了一些阅读。几个好消息来源: One Two

现在这两个教程都讨论了Nim游戏中的S-G定理。 使用Nim, - 我知道你需要递归分支树来找到每个游戏的grundy数,你可以从一开始就应用XOR函数,并立即解决它。 (你不需要为nim扩展树的原因,是因为你知道一堆N个硬币,有一个数量很多的N - 你知道这一点通过思考它 - 例如,一堆3,扩展可以是一堆2,1或0,一堆2可以是0,1,一堆1只能变成0,所以1有一个数量为1,2有一个数量为2的3,有3个grundy数量为3 ...)。

同样,对于this tutorial中提到的马棋比赛,我们可以预处理棋盘上每个位置的grundy数字,并查看我们的棋盘配置的那些grundy数字并应用XOR功能。

但我并没有发现如何将此问题应用于此问题。 甚至社论似乎也暗示了一些递归:

  

游戏分为两个子游戏,S(i,a-1)和S(b + 1,j)。因为玩家可以选择任何游戏,所以游戏的Grundy数字只是两个子游戏的Grundy数字的异或。

是的 - 它似乎还涉及到仍在扩展树,直到找到失败的位置,然后将其传递出去。

就像这样:

 def recursiveFunction(string):
     set = []
     for word in dictionary:
         if word is in string: 
             remove word from string and split the remaining string:
             set.add(recursiveFunction(string-a) XOR recursiveFunction(string-b))
     return mex(set)

我看不出这与min-max解决方案有很大不同。 实际上 - 不是最小 - 最大更快吗? - 因为min-max可以在找到胜利分支后退出,而S-G需要继续尝试每个单词。

所以,我需要澄清我对S-G定理的使用,或者这只是优化我当前算法的问题。例如,我不认为我需要在每次迭代中进行字符串搜索,我只能存储索引位置。

0 个答案:

没有答案