I've got a problem with applying a Bellman-Ford algorithm to 2D Array (not to graph)
Input array has m x n dimensions:
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]
And it is room-alike (each entry is a room with s[x,y] cost of enterance). Each room could have also a negative cost, and we have to find cheapest path from Entry to choosen room and to Exit.
For example, we've got this array of rooms and costs:
1 5 6
2 -3 4
5 2 -8
And we want to walk over room [3,2], s[3,2] = 4. We are starting form 5 at [1,3] and must walk over [3,2] before we go to [3,3].
And my question is, what is the best way to implement it in Bellman-Ford algorithm? I know that Dijkstry algorithm will not work becouse of negative cost.
Is for each room from [0, maxHeight] and relax all neighbors correct? Like this:
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);
}
}
But how can I then read a cost to choosen room and from room to exit?
The Bellman-Ford algorithm is an example of Dynamic Programming. It starts with a starting vertex and calculates the distances of other vertices which can be reached by one edge. It then continues to find a path with two edges and so on. The Bellman-Ford algorithm follows the bottom-up approach.
Bellman-Ford Sequential Algorithm Bellman-Ford algorithm is a simple algorithm which uses edge relaxation technique. It relaxes all the edges, | V | − 1 times. Where | V | is the number of vertices in the graph. It can also work on the graph with negative weight edges provided there is no negative edge cycle.
Yes. It works in dynamic programming approach. It calculates shortest paths in bottom-up manner. Intermediate values are stored and used for next level values.
If you know how to move on the graph from an array, you can scroll to additional condition paragraph. Read also next paragraph.
In fact, you can look at that building like on a graph.
You can see like: (I forgot doors in second line, sorry.)
So, how it is possible to be implement. Ignore for the moment additional condition (visit a particular vertex before leaving).
Weight function:
Let S[][]
be an array of entry cost. Notice, that about weight of edge decides only vertex on the end. It has no matter if it's (1, 2) -> (1,3)
or (2,3) -> (1, 3)
. Cost is defined by second vertex. so function may look like:
cost_type cost(vertex v, vertex w) {
return S[w.y][w.x];
}
//As you can see, first argument is unnecessary.
Edges:
In fact you don't have to keep all edges in some array. You can calculate them in function every time you need.
The neighbours for vertex (x, y)
are (x+1, y)
, (x-1, y)
, (x, y+1)
, (x, y-1)
, if that nodes exist. You have to check it, but it's easy. (Check if new_x > 0 && new_x < max_x.) It may look like that:
//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;
}
Generating neighbours can look like:
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);
}
}
I believe, that it shouldn't take extra memory for four edges. If you don't know std::tie, look at cppreference. (Extra variables x
, y
take more memory, but I believe that it's more readable here. In your code it may not appear.)
Obviously you have to have other 2D array with distance and (if necessary) predecessor, but I think it's clear and I don't have to describe it.
Additional condition:
You want to know cost from enter to exit, but you have to visit some vertex compulsory
. Easiest way to calculate it is to calculate cost from enter
to compulsory
and from compulsory
to exit
. (There will be two separate calculations.) It will not change big O time. After that you can just add results.
You just have to guarantee that it's impossible to visit exit
before compulsory
. It's easy, you can just erase outgoing edges from exit
by adding extra line in is_correct function, (Then vertex v
will be necessary.) or in generating neighbours code fragment.
Now you can implement it basing on wikipedia. You have graph.
Why you shouldn't listen?
Better way is to use Belman Ford Algorithm from other vertex. Notice, that if you know optimal path from A to B, you also know optimal path from B to A. Why? Always you have to pay for last vertex and you don't pay for first, so you can ignore costs of them. Rest is obvious.
Now, if you know that you want to know paths A->B and B->C, you can calculate B->A and B->C using one time BF from node B and reverse path B->A. It's over.
You just have to erase outgoing edges from entry
and exit
nodes.
However, if you need very fast algorithm, you have to optimize that. But it is for another topic, I think. Also, it looks like no one is interested in hard optimization.
I can quickly add, just that small and easy optimization bases at that, that you can ignore relaxation from correspondingly distant vertices. In array you can calculate distance in easy way, so it's pleasant optimization.
I have not mentioned well know optimization, cause I believe that all of them are in a random course of the web.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With