搜索多分支图并返回路径[C#]

时间:2017-09-04 15:10:46

标签: search graph path-finding

在我的情况下,我有领土对象。每个地区都知道他们通过阵列连接的其他地区。以下是地图上显示的所有地区的可视化:

enter image description here

如果您要绘制图表上的连接,它们将如下所示:

enter image description here

所以说我有一个驻守在[b]区域的单位,我想把它移到领土[e],我正在寻找一种搜索这个图并返回代表最终数组的方法我的单位在[b]区域必须采取的路径。在这种情况下,我会寻找它返回

[b, e].

如果我想从领土[a]到领土[f],那么它会返回:

[a, b, e, f].

我会喜欢这样的例子,但即使只是指向我正确方向的帖子也会受到赞赏。提前致谢! :)

1 个答案:

答案 0 :(得分:0)

您之前听说过广度优先搜索(BFS)吗?

基本上,您只需将您的初始区域“示例”中的“a”放入另外的空队列中Q

您需要的第二个数据结构是一系列布尔值,其元素与您拥有的区域一样多,在本例中为9.它有助于记住我们已检查过的区域。我们称之为V(对于“已访问”)。它需要初始化如下:除了与初始方块对应的元素外,所有元素都等于false。这适用于所有地区t,我们有V [t] = false,但是V [a] = true,因为“a”已经在队列中。

您需要的第三个也是最后一个数据结构是一个存储父节点的数组(即我们来自哪个节点)。它还拥有与您拥有的区域一样多的元素。我们将其称为P(对于“父”),并且每个元素最初都指向自身,即对于P中的所有t,设置P [t] = t。

然后,这很简单:

while Q is not empty:
   t = front element in the queue (remove it also from Q)
   if t = f we can break from while loop //because we have found the goal
   for all neighbors s of t for which V[s] = false:
       add s into the back of Q //we have never explored the territory s yet as V[s] = false
       set V[s] = true //we do not have to visit s again in the future

       //we found s because there is a connection from t to s
       //therefore, we need to remember that in s we are coming from the node t
       //to do this we simply set the parent of s to t:
       P[s] = t

你现在如何阅读解决方案?

只需检查f的父级,然后检查其父级,然后检查其父级,依此类推,直到找到开头。一旦找到一个自己作为父元素的元素,你就会知道它的起点是什么(记住我们最初让它们指向自己),或者你也可以将它与a进行比较。 基本上,你只需要一个空列表L,在其中添加f然后

while f != a:
    f = P[f]
    add f into L

请注意,如果没有路径,这显然会失败,因为f永远不会等于a。 因此,这个:

while f != P[f]:
    f = P[f]
    add f into L

有点好。它利用了这样一个事实,即最初所有地区都指向P。

如果您在上面的示例中尝试使用纸张,那么您最终会得到 L = [f,e,b,a] 如果您只是反转此列表,那么您就拥有了所需的内容。

我不知道C#,所以我不打算使用C#语法。我假设你知道用整数索引你的地区是最简单的,然后使用数组来访问它们。

你会很快意识到为什么会这样。它被称为广度优先搜索,因为您首先只考虑区域“a”的邻居,只有最短的路径(只有1条边),只有处理了所有这些后,才会出现更远的区域(从现在开始只有2个边缘),依此类推。这就是我们为此任务使用队列而不是堆栈的原因。

此外,这是区域和边缘数量的线性,因为您只需要查看每个区域和边缘(最多)一次(尽管来自两个方向的边缘)。

我给你的算法与https://en.wikipedia.org/wiki/Breadth-first_search基本相同,只添加了P数据结构,以便跟踪你来自哪里,以便能够找出所采用的路径。