我在这里问这个,因为我没有在代码厨师论坛上得到答案。 Thread at codechef.
你好。这是我做过的第一个问题。我收到了TLE错误。所以我最初的方法是创建一个 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定理的使用,或者这只是优化我当前算法的问题。例如,我不认为我需要在每次迭代中进行字符串搜索,我只能存储索引位置。