通过图表递归遍历,计算点到点

时间:2011-12-19 22:38:53

标签: graph traversal depth-first-search

得到一张如下图所示的图表:example

我想从该图中的p(0,0)计算到特定点p(i,j)的所有可能方法。我想我可以用深度优先搜索来做到这一点。我应该如何扩展深度优先搜索,所以它不计算两次?

2 个答案:

答案 0 :(得分:1)

最好的方法是在不实际跟踪所有路径的情况下计算路数。让F(x, y)成为到达目的地点的方式。然后,您可以在图表中看到F(x, y) = F (x+1, y) + F (x, y+1) + F(x+1, y+1)。你想要F(0,0)。你的基本情况将是F(i, j) = 1(如果你已经在那里,可以到达那里的一种方式:不去任何地方)和F(any number > i, any j) and F(i, any number > j) = 0,因为一旦你'没有办法到达目的地点'通过它。

更新详情:现在如何评估此公式?你可以递归地做,但一个天真的实现将是非常低效的。一个天真的实现就像伪代码那样松散地看起来像python:

i = ...
j = ...
def paths (x, y):
    if (x > i) or (y > j):
        return 0         
    if (x == i) and (y == j):
        return 1
    else:
        return paths (x+1, y) + paths (x, y+1) + paths (x+1, y+1)
print F(0, 0)

这个问题是,如果你从(0,0)开始,你的第一级递归调用将是(0,1),(1,0)和(1,1)。当这些调用反过来评估时,(0,1)将计算(0,2)(1,1)和(1,2);然后(1,0)将计算(1,1),(2,0)和(2,1),然后(1,1)将计算(1,2),(2,1)和( 2,2)。请注意,这些调用中有多少是冗余的,因为它们计算的值相同。解决此问题的方法是保留一个记忆F值的矩阵。那么代码可能看起来像这样:

i = ...
j = ...
memorizedValues = ... #make an i by j grid filled with -1
memorizedValues[i][j] = 1 #initial condition

def paths (x, y):
    if (x > i) or (y > j):
        return 0
    if (memorizedValues[x][y] != -1): #check for a memorized value before
        return memorizedValues[x][y] # starting more recursion!
    else:
        memorizedValues[x][y] = paths (x+1, y) + paths (x, y+1) + paths (x+1, y+1)
        return memorizedValues[x][y]

print F(0, 0)

这仍然不是最有效的实现方式,但我认为它可以解决问题。它比通过跟踪和回溯计算每条路径要快得多!

答案 1 :(得分:1)

您可以使用BFS并标记节点或使用地图来跟踪它们。但是,如果您的图表很大,BFS需要将其全部保存在内存中。 DFS更擅长。但是,除非您对其进行深度限制,否则DFS可能会丢失在大图中。

无论如何,为了加快您的计划,您可以考虑提前停止:

  • 图表已断开连接
  • 你到达桥梁

其他启发式:

  • 首先访问1级邻居,然后再继续。

我写了一个类似的程序,看看我能在多大程度上优化它:  https://github.com/eamocanu/allPathsFinder