📜  谜题 70 |汤姆和杰瑞(1)

📅  最后修改于: 2023-12-03 15:28:12.120000             🧑  作者: Mango

谜题 70 | 汤姆和杰瑞

简介

该谜题源于计算机科学家 Donald E. Knuth 在 1974 年创作的《计算机编程艺术》第一卷第一章的习题 70,也被称为“汤姆和杰瑞”(Tom and Jerry)问题。

该问题可以用图论的方式进行建模,并在计算机算法领域中具有重要的应用。

问题描述

问题描述如下:

在一个二分图中,分别有 $m$ 个左顶点和 $n$ 个右顶点,其中每个左顶点有 $p$ 条边与右顶点相连。

现在,假设一只老鼠从二分图的左侧出发,每次可以随机地选择一个相邻的顶点移动,直到到达二分图的右侧。

请问,老鼠达到右侧的期望步数是多少?

解题思路
第一步:建图

首先将二分图生成一下。

可以用 Python3 中的 NetworkX 库来实现:

import networkx as nx

def complete_bipartite_graph(m, n):
    """
    生成一个 m x n 的二分图,其中左侧有 m 个顶点,右侧有 n 个顶点,每个左侧顶点有 n 个右侧顶点相邻。
    """
    G = nx.Graph()
    G.add_nodes_from(["L{}".format(i) for i in range(1, m + 1)], bipartite=0)
    G.add_nodes_from(["R{}".format(i) for i in range(1, n + 1)], bipartite=1)
    G.add_edges_from([("L{}".format(i), "R{}".format(j)) for i in range(1, m + 1) for j in range(1, n + 1)])
    return G

使用方式:

>>> G = complete_bipartite_graph(2, 3)
>>> G.edges()
[('L1', 'R1'), ('L1', 'R2'), ('L1', 'R3'), ('L2', 'R1'), ('L2', 'R2'), ('L2', 'R3')]
>>> nx.draw(G, with_labels=True)

image-20211019150057608

第二步:计算期望

假设 $E_{i,j}$ 表示在第 $i$ 步时到达左侧第 $j$ 个顶点时达到右侧的期望步数。

$E_{i,j}$ 可以通过 $E_{i-1}$ 计算得出。

由于每个左侧顶点有 $p$ 条边与右侧相邻,因此第 $i$ 步到达左侧第 $j$ 个顶点时,有 $1/p$ 的概率直接到达右侧。

否则,到达左侧第 $j$ 个顶点后,需要从它相邻的右侧顶点中随机选择一个顶点进入下一步,因此有 $1/(pm)$ 的概率移动到右侧相邻的某个顶点,有 $p-1$ 的概率留在原地等待下一步移动。

因此,

$$ E_{i,j}=1+\frac{1}{p}\sum_{k=1}^{n}E_{i-1,k}+\frac{p-1}{p}\cdot E_{i,j} $$

化简得:

$$ E_{i,j}=\frac{1}{p}\sum_{k=1}^{n}E_{i-1,k}+\frac{p}{p-1} $$

边界条件:$E_{0,j}=0$ (二分图的左侧没有起点)

下面是 Python3 中的示例代码:

def tom_and_jerry(G):
    """
    给定一个二分图 G,计算老鼠从左侧到达右侧的期望步数
    """
    m = len([n for n, p in G.nodes(data="bipartite") if p == 0])
    n = len([n for n, p in G.nodes(data="bipartite") if p == 1])
    p = len(list(G.neighbors("L1")))
    
    E = [0] * (n+1) # E[0] 不作为左侧的起点
    for i in range(1, m+1):
        E_next = [0] * (n+1)
        for j in range(1, n+1):
            E_next[j] = sum([E[k] for k in range(1, n+1) if k != j]) / (p*m) + p / (p-1)
        E = E_next
    
    return E[n]
参考资料
  • Knuth, D. E. (1997). 第一卷:基本程序设计技巧.
  • Eric Greveson. (2018). Tom and Jerry - A problem from Knuth's "The Art of Computer Programming".