二维阵列中的Belman-Ford算法

时间:2015-10-27 21:26:35

标签: c++ c algorithm graph

我将Bellman-Ford算法应用于2D阵列时遇到了问题(不是图表)

输入数组具有 m x n 维度:

           s[1,1] s[1,2] ... s[1,n] -> Exit
           s[2,1] s[2,2] ... s[2,n]
           ...
 Entry ->  s[m,1] s[m,2] ... s[m,n]

它是相似的房间(每个条目都是 s [x,y] enterance成本的房间)。每个房间也可能有负成本,我们必须找到最便宜的路径,从进入选择房间到退出

例如,我们有这样的房间和费用:

1   5   6
2  -3   4
5   2  -8

我们想走过房间 [3,2] s [3,2] = 4。我们正在开始 5 [1,3] 并且在我们去 [3,3] 之前必须走过 [3,2]

我的问题是,在Bellman-Ford算法中实现它的最佳方法是什么?我知道Dijkstry算法不会因负成本而起作用。

从[0,maxHeight]的每个房间是否放松所有邻居?像这样:

   for (int i = height-1; i >= 0; --i) {
        for (int j = 0; j < width; ++j) {
            int x = i;
            int y = j;
            if (x > 0) // up
                Relax(x, y, x - 1, y);
            if (y + 1 < width) // right
                Relax(x, y, x, y + 1);
            if (y > 0) // left
                Relax(x, y, x, y - 1);
            if (x + 1 < height) // down
                Relax(x, y, x + 1, y);
        }
    }

但是,如何才能读取选择房间以及从房间退出的费用?

1 个答案:

答案 0 :(得分:10)

如果您知道如何从数组移动图形,则可以滚动到附加条件段落。另请阅读下一段。

实际上,您可以在图表上查看该建筑物。

enter image description here 你可以看到:(我在第二行忘记了门,对不起。) enter image description here

那么,如何实施呢?暂时忽略附加条件(离开前访问特定顶点) 体重功能
S[][]成为一个入门成本数组。注意,关于边缘的权重仅决定末端的顶点。它无论是(1, 2) -> (1,3)还是(2,3) -> (1, 3)都有。成本由第二个顶点定义。所以功能可能如下:

cost_type cost(vertex v, vertex w) {
    return S[w.y][w.x];
}
//As you can see, first argument is unnecessary.

边缘
实际上,您不必将所有边缘保留在某个数组中。您可以在每次需要时计算它们。 如果节点存在,则顶点(x, y)的邻居为(x+1, y)(x-1, y)(x, y+1)(x, y-1)。你必须检查它,但它很容易。 (检查new_x&gt; 0&amp;&amp; new_x&lt; max_x。)它可能看起来像这样:

//Size of matrix is M x N
is_correct(vertex w) {
    if(w.y < 1 || w.y > M || w.x < 1 || w.x > N) {
        return INCORRECT;
    }
    return CORRECT;
}

生成邻居可能如下所示:

std::tie(x, y) = std::make_tuple(v.x, v.y);
for(vertex w : {{x+1, y}, {x-1, y}, {x, y+1}, {x, y-1}}) {
    if(is_correct(w) == CORRECT) {//CORRECT may be true
        relax(v, w);
    }
}

我相信,它不应该为四个边缘占用额外的内存。如果你不知道std::tie,请查看cppreference。 (额外变量xy需要更多内存,但我相信它在这里更具可读性。在您的代码中可能不会出现。)

显然你必须有其他具有距离的2D数组和(如有必要)前任,但我认为它很清楚,我不必描述它。

附加条件
您想知道从进入退出的成本,但您必须访问某些顶点compulsory。最简单的计算方法是计算从entercompulsory以及从compulsoryexit的费用。 (将有两个单独的计算。)它不会改变big O时间。之后,您可以添加结果。

您必须保证在exit之前无法访问compulsory。这很容易,你可以通过在is_correct函数中添加额外的行来清除exit的传出边缘(然后需要顶点v。)或者生成邻居代码片段。

现在你可以实现它basing on wikipedia。你有图表。

为什么你不应该听?
更好的方法是从其他顶点使用Belman Ford算法。请注意,如果您知道从A到B的最佳路径,您还知道从B到A的最佳路径。为什么?总是你必须支付最后一个顶点并且你不需要先付费,所以你可以忽略它们的成本。休息很明显。
现在,如果您知道您想要知道路径A-> B和B-> C,则可以使用来自节点B的一次BF和反向路径B来计算B-> A和B-> C. ;一个。结束了。
您只需要清除entryexit节点的传出边缘。

但是,如果您需要非常快速的算法,则必须对其进行优化。但我认为这是另一个话题。此外,似乎没有人对硬优化感兴趣 我可以快速添加,只是那个小而简单的优化基础,你可以忽略相应的遥远顶点的放松。在数组中,您可以轻松地计算距离,因此它是令人愉快的优化。
我没有提到很好的优化,因为我相信所有这些都是在网络的随机过程中。

相关问题