我在这里问这个,因为我在代码厨师论坛上没有得到答案。
这是我解决的第一个问题。我收到 TLE 错误。
所以我最初的方法是创建一个Min-Max 游戏树。这是我最近的解决方案。
伪码算法是:
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 错误,所以我在这里查看了执行此操作的指南。
社论建议使用Sprague-Grundy 定理。阅读了一些关于使用 SG 定理的内容。几个好的来源 :一二 。
现在,这两个教程都在 Nim 游戏的背景下讨论 SG 定理。使用 Nim,-我知道您不需要递归地分支树来查找每个游戏的 grundy 数字,您可以从一开始就应用 XOR 函数,并立即解决它。(你不需要为 nim 扩展树的原因是因为你知道一堆 N 个硬币,有一个糟糕的 N - 你通过思考知道这一点 - 例如,一堆 3,扩展可以是一堆2、1还是0,一堆2可以是0、1,一堆1只能变成0,所以1的grundy数是1,2的grundy数是2,3有一个3 的脏数字...)。
同样,对于本教程中提到的马棋游戏,我们可以对棋盘上每个位置的粗略数字进行预处理,并为我们的棋盘配置查找这些粗略数字并应用 XOR 函数。
但是我发现我们如何将其应用于这个问题并不是那么清楚。甚至社论似乎也暗示涉及一些递归:
游戏分为两个子游戏,S(i, a-1) 和 S(b+1, j)。因为玩家可以在他/她的回合中选择任何游戏,所以游戏的 Grundy 数只是两个子游戏的 Grundy 数的 XOR。
即 - 它似乎仍然涉及扩展树直到你找到一个失败的位置,然后传递它。
即是这样的:
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更快?- 因为 min-max 一旦找到获胜的分支就可以退出,而 SG 需要继续尝试每个单词。
所以,要么我需要澄清我对 SG 定理的使用,要么这只是优化我当前算法的问题。例如,我认为我不需要每次迭代都进行字符串搜索,我可以只存储索引位置。