Algorithm 树搜索算法:如何快速确定A是否有必胜策略

Algorithm 树搜索算法:如何快速确定A是否有必胜策略,algorithm,tree,Algorithm,Tree,原来的问题是这样的:有99块石头,A和B在玩一个游戏,每个人轮流拿一些石头,每个回合只能拿1、2、4或6块石头,拿最后一块石头的人获胜。如果A是第一个拿石头的人,A在第一轮应该拿多少石头 这似乎是一个相当复杂的树搜索测验,列出所有的树枝,然后自下而上地进行:叶子上的一块石头被标记为“赢”;对于中间节点,无论B采取何种策略,如果A始终有办法到达标记为“赢”的节点,则该节点也标记为“赢” 但这种方法相当耗时。是否有任何智能算法可以检查A是否有“保证获胜”策略?O(n)解决方案 如果我们从1、2、4或

原来的问题是这样的:有99块石头,A和B在玩一个游戏,每个人轮流拿一些石头,每个回合只能拿1、2、4或6块石头,拿最后一块石头的人获胜。如果A是第一个拿石头的人,A在第一轮应该拿多少石头

这似乎是一个相当复杂的树搜索测验,列出所有的树枝,然后自下而上地进行:叶子上的一块石头被标记为“赢”;对于中间节点,无论B采取何种策略,如果A始终有办法到达标记为“赢”的节点,则该节点也标记为“赢”

但这种方法相当耗时。是否有任何智能算法可以检查A是否有“保证获胜”策略?

O(n)解决方案

如果我们从1、2、4或6块石头开始,A总是会赢,因为他会在第一步就把它们全部拿走

如果我们从3开始,
A
无论做什么都会输,因为无论他拿1还是2,
B
下一个拿2还是1,都会赢

如果我们从5开始,
A
将首先获得2,从而将
B
发送到上面的案例中,他从3块石头开始

如果我们从7开始,
A
将以
4
获胜,将
B
发送到与
3
相同的案例

如果我们从8开始,
A
无论他做什么都会失败:无论他拿什么,他都会把
B
送到胜利的位置

如果我们从9开始,
A
可以取1,然后将
B
发送到有8的情况,导致他失败

如果我们从10开始,
A
可以取2,然后将
B
再次发送到8的情况,导致他失败

到目前为止,您应该非常清楚如何以增量方式构建一个
O(n)
解决方案:如果第一个移动的人可以赢得我的石头,那么让
win[i]=true

我们有:

win[1] = win[2] = win[4] = win[5] = win[6] = true, win[3] = false
win[x > 6] = not (win[x - 6] and win[x - 4] and win[x - 2] and win[x - 1])
例如:

win[7] = not (win[1] and win[3] and win[5] and win[6])
       = not (true and false and true and true)
       = not false
       = true
计算这个直到你感兴趣的数字,就这样。没有涉及树木

O(1)解决方案

通过仔细观察上述解决方案,我们可以得出一个简单的常数时间解决方案:注意,
a
只有在他将
B
发送到获胜位置时才会失败,无论他做什么,因此如果
k-6、k-4、k-2、k-1
都是获胜位置

如果您为几个值计算
win
,则模式变得明显:

win[k] = false if k = 3, 8, 11, 16, 19, 24, 27, 32...
=> win[k] = false iff k mod 8 == 3 or k mod 8 == 0

对于99,
99 mod 8=3
,因此
A
没有确定的获胜策略。

好的,我们可以看到:

每转一圈,可以取的石头数小于7,因此结果应与模数7相关

所以,对于n<1000,我已经打印出了第一人称获胜的石头数量顺序,模数7,这是一个真正重复的循环

1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 0 1 3 4 5 6 1 2 4 5 6 0 2 3 5 6 0 1 3 4 6 0 1 2 4 5 0 1 2 3 5 6 1 2 3 4 6 0 2 3 4 5 

此循环的长度为56,因此可以通过查找前56个数字的结果在O(1)中解决问题。

问题标题应具有信息性。@sashoalm编辑,现在可以了吗?这个游戏也被称为Nim-google,我认为它有点不同:Nim游戏允许玩家使用少于一个数字的某些石头,但这个游戏只允许1、2、4和6。会有什么不同吗?@500 InternalServerError-这不完全是尼姆。如果你说它可以简化为Nim,我不认为这是显而易见的。我认为我发现了一个更有用的序列(答案如下),循环的长度是56,除以8。出于好奇,你怎么能想出数字8?@PhamTrung-我注意到当
k mod 8=0
时,
win[k]=false
,但在其他情况下也是如此。然后我注意到这些情况只发生在
k mod 8=3
时,所以我将两者结合起来。不过我不会说这更有用:你必须找到一个完整的序列,而不仅仅是取一个模。