找出谁在遍历游戏中获胜的算法

Posted

技术标签:

【中文标题】找出谁在遍历游戏中获胜的算法【英文标题】:Algorithm to find who wins in traversal game 【发布时间】:2019-02-14 13:03:33 【问题描述】:

我们将使用图表和两个玩家。在这个连通图中,获胜条件是第二个玩家没有其他路径可走。问题是一旦玩家选择了一条路径,就不能再选择了。

让我们假设初始输入是邻接表 (x,y) 意味着 x 有到 y 的路径

我们的目标是返回一组顶点,玩家 1 可以选择这样它总是会获胜。

例如,如果我有 [(1,2), (2,0), (0, 3), (3,2)] 并且玩家 1 开始,那么我们应该返回 [1, 0, 3]。我们无法返回2

2 --> 玩家 1 从这里开始

(2,0) --> 玩家 2 去 0

(0,3) --> 玩家 1 去 3

(3,2) --> 玩家 2 去 2

(2,0) --> 玩家 1 不能去这里,已经被占领了

already_visited = []

turn = 1

result = []

def findStarting(L):
    global already_visited
    global turn
    global result

    for x,y in L:
        allowed = can_visit(L, y) # function tell me which I can visit safely

        turn = (turn % 2) + 1 # increment the turn

        already_visited.append((x,y)) # we visited this edge

        res = findStarting([(x, y)]) # recursive call (search on this node for paths)


    if (turn == 2): return True

def can_visit(L, y): 
    res = []
    for a,b in L: if (a==y and (a,b) not in already_visited): res.append((a,b))
    return res

我在递归情况下遇到了麻烦。我想我想要做的是返回True,如果我们到达一个转折点并且玩家没有他们可以走的路径,但我不知道如何从这里继续前进

【问题讨论】:

【参考方案1】:

这是一个简单的递归解决方案。它效率不高,它是蛮力搜索,没有任何中间状态缓存,所以它肯定可以更快,虽然我不知道是否有一个有效(即非指数)的解决方案来解决这个问题。

def firstPlayerWins(g,v):
  for i,e in enumerate(g):
    if e[0]==v and not firstPlayerWins(g[:i]+g[i+1:],e[1]):
        return True
  return False

def winningVertices(g):
  return [v for v in set(e[0] for e in g) if firstPlayerWins(g,v)]

winningVertices([(1,2), (2,0), (0, 3), (3,2)])
## [0, 2, 3]

【讨论】:

这并不完全正确。例如 winningVertices([(0,1),(1,2)]) 应该返回 [1,2] 但只返回 [1] 2 在这种情况下不会获胜。从 2 开始,第一个玩家没有可用的动作并且输了。 我们假设第一个玩家最初“移动到”2。因此,在他们到达第一个顶点之后,对手移动。从这个意义上说,从技术上讲,所有没有向外连接的节点都是有效的候选节点 对不起,我写错了最初的指令。实际上上面的例子(我问题中的原始例子)应该返回[0,1,3](不是2) 在这种情况下,情况正好相反,因为实际上玩家 2 在玩家 1 选择起始顶点之后先行。在您的示例中,正确答案实际上只是[1],而[0,2,3] 是第二个玩家获胜的顶点。基本上,只需将函数重命名为 losingVertices 而不是 winningVertices

以上是关于找出谁在遍历游戏中获胜的算法的主要内容,如果未能解决你的问题,请参考以下文章

算法leetcode|1823. 找出游戏的获胜者(rust太好用了)

算法leetcode|1823. 找出游戏的获胜者(rust太好用了)

LeetCode 1823 找出游戏的获胜者[队列 模拟 数学] HERODING的LeetCode之路

约瑟夫环——递推公式详解(leetcode 1823. 找出游戏的获胜者)

leetcode.1275找出井字棋的获胜者

LeetCode 937. 重新排列日志文件 / 1823. 找出游戏的获胜者(约瑟夫环问题) / 713. 乘积小于 K 的子数组