36

I know that many algorithms are available for calculating the shortest path between two points in a graph or a grid, like breadth-first, all-pairs (Floyd's), Dijkstra's.

However, as I noticed, all of these algorithms compute all the paths in that graph or grid, not only those between the two points we are interested in.

MY QUESTION IS: if I have a grid, i.e. a two dimensional array, and I'm interested in computing the shortest path between two points, say P1 and P2, and if there are restrictions on the way I can move on the grid (for example only diagonally, or only diagonally and upwards, etc.), what algorithm can compute this?

Please notice here that if you have an answer, I would like you to post the name of the algorithm rather than the algorithm itself (of course, even better if you also post the algorithm); for example, whether it is Dijkstra's algorithm, or Floyd's, or whatever.

Please help me, I've been thinking about this for months!


okey guys i found this algorithm on TOPCODER.COM here in the grid you can move only (diagonally and up) but i can't understand what algorithm is this by any means could any one know?

#include<iostream>
#include <cmath>

using namespace std;




inline int Calc(int x,int y)

{



if(abs(x)>=abs(y)) return abs(x);
int z=(abs(x)+abs(y))/2;
return z+abs(abs(x)-z);
 }

class SliverDistance
{


    public:
int minSteps(int x1,int y1, int x2, int y2)
{
    int ret=0;
    if(((x1+y1)&1)!=((x2+y2)&1))y1++,ret++;
    return ret+Calc(x2-x1,y2-y1);
}
};
Kev
  • 118,037
  • 53
  • 300
  • 385
Alan_AI
  • 1,529
  • 3
  • 22
  • 32
  • 1
    Do you want the *length* of the shortest path or the actual path? Is the grid guaranteed to be unobstructed and uniform in "cost" to traverse? – NVRAM Feb 22 '10 at 16:40
  • i want the length of the shortest path, the grid is completely uniform , think of it as a cartesian plane whose coordiantes are integers – Alan_AI Feb 22 '10 at 16:49
  • 1
    Dijkstra's doesn't necessarily compute the shortest paths to all other points on the graph. It to needs to compute the shortest paths to every point that has a shorter path than your goal (and it might also find the path to points that have the same length of shortest path as your goal point). Then it might go one point beyond these points, but that should be all. – Justin Peel Feb 22 '10 at 16:59

8 Answers8

46

Lee's algorithm: http://en.wikipedia.org/wiki/Lee_algorithm

It's essentially a BF search, here's an example: http://www.oop.rwth-aachen.de/documents/oop-2007/sss-oop-2007.pdf

To implement it effectively, check my answer here: Change FloodFill-Algorithm to get Voronoi Territory for two data points? - when I say mark, you mark it with the number on the position you came from + 1.

For example, if you have this grid, where a * = obstacle and you can move up, down, left and right, and you start from S and must go to D, and 0 = free position:

S 0 0 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

You put S in your queue, then "expand" it:

S 1 0 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

Then expand all of its neighbours:

S 1 2 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

And all of those neighbours' neighbours:

S 1 2 3
* * 3 *
* 0 0 *
0 0 * *
* 0 0 D

And so on, in the end you'll get:

S 1 2 3
* * 3 *
* 5 4 *
7 6 * *
* 7 8 9

So the distance from S to D is 9. The running time is O(NM), where N = number of lines and M = number of columns. I think this is the easiest algorithm to implement on grids, and it's also very efficient in practice. It should be faster than a classical dijkstra, although dijkstra might win if you implement it using heaps.

Community
  • 1
  • 1
IVlad
  • 43,099
  • 13
  • 111
  • 179
  • please check the algorithm i post it as an answer – Alan_AI Feb 22 '10 at 15:25
  • Ok, this is a much better explanation of Ala's question. Now I understand exactly what he was asking for, but I still wouldn't have known this answer. Interesting! – Dave Feb 22 '10 at 15:39
  • 2
    In the ancient past I used the Lee algo for PCB layout; we made the cells in the current direction less expensive than ones to the side: thus we avoid "jagged" lines in favor of straight ones. – NVRAM Feb 22 '10 at 16:24
  • Oh, and `"only diagonally"` would be simple to implement. Note that since the "sparks" grow from all/both endpoints `"only diagonally and upwards"` would require you first classify which point is "higher" and have its spark only progress *downward*. – NVRAM Feb 22 '10 at 16:27
  • "Then expand all of its neighbors:" what do you mean by that? to add all of the unvisited neighbors to the queue? – shinzou Dec 26 '15 at 09:46
  • @kuhaku yes, exactly. – IVlad Dec 26 '15 at 16:35
  • Much better than the wikipedia explanation. Thanks! – Mark Gardner Feb 23 '17 at 07:27
  • Thanks, this algorithim did the trick for me! This [link](https://www.codesdope.com/blog/article/lee-algorithm/) gave me some futher info on implementing it. – RcoderNY Dec 24 '22 at 05:10
6

Use the A Star (A*) algorithm.

William Price
  • 4,033
  • 1
  • 35
  • 54
newdayrising
  • 3,762
  • 4
  • 27
  • 31
6

You may be disinformed. There exist different variants of Dijkstra's algorithm. One computes the shortest paths from each point to every other point (like Floyd's).

However, the typical Dijkstra algorithm is based on a priority queue and only computes your required shortest path. It does construct several paths during its execution, but those are all partial paths from A to some other nodes that might be on the final solution path.

Hence, you can easily interpret your grid as a graph (the restrictions like diagonals can then be taken into account accordingly) and run a Dijkstra search for the shortest path from A to B on that. It's really just a matter of modelling your problem, not that you need some fancy algorithm.

Frank
  • 10,461
  • 2
  • 31
  • 46
  • +1 for making sure one thinks of their problem properly. I stumbled on this question thinking I needed a shortest path algorithm, but this helped me realize that while it would have worked for my problem eventually, it wasn't what I was really trying to solve. – devyndraen Mar 31 '19 at 06:13
2

If your movement is restrictive enough (e.g. you can only move to the right, or up, or to the diagonal up and right), then you can exploit its overlapping subproblems and suboptimal substructure nature and use dynamic programming.

polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 1
    This algorithm is called DAG-shortest path, and as implied by the name, works only on directed acyclic graphs. – rettvest Feb 22 '10 at 16:39
  • @stubbscroll This is why @polygenelubricants says `restrictive enough'. In the examples that polygenelubricants mentions, one has to deal with directed acyclic graphs (DAGs). So, it is still a very useful comment related to the question at hand. – MightyMouse Feb 17 '15 at 22:49
1

What I fail to understand is, if you want the shortest path between A and B, don't you still need to look at A to C and A to D if C and D point to B? Your shortest path could very well be A-C-B or A-D-B. You just need to throw out unconnected nodes. In one of my projects, I took points A and B, checked to see what other points were connected, and those that weren't were deleted from the entire graph. Then I proceeded with using Dijkstra's algorithm.

Dave
  • 14,618
  • 13
  • 91
  • 145
  • i don't to compute the path, i.e. the algorithm doesn't know how to move from A to B, it only know the shortest path between them depenting on there coordinates, p.s. it's not a graph it's a grid in which every node has coordinates – Alan_AI Feb 22 '10 at 14:58
  • FYI: If you just want the shortest path from A to B using Dijkstra you do not need to check connectivity first and delete unreachable elements. In fact, this worsens your runtime complexity, as Dijkstra will implicitly decide connectivity between A and B and may only need to look at a small subgraph for that, whereas you look at the whole graph when deleting elements. – Frank Feb 22 '10 at 15:02
  • @Frank: I never actually did any benchmarking, but conceptually, it just seemed that if I had 100 nodes in the graph, Dijkstra is going to visit each one and then weight the cost of the path from node to node. But if I can remove 95 of the 100 nodes up front, why wouldn't I want to do that, instead of letting Dijkstra's deal with it as it processes the graph? – Dave Feb 22 '10 at 15:36
  • @Ala: sorry, I got caught up in Dijkstra and failed to remember that you are using a grid. :) – Dave Feb 22 '10 at 15:37
  • so guys, check the algorithm i posted as an answer – Alan_AI Feb 22 '10 at 15:59
1

Here's a python implementation of shortest path in a matrix from (0,0) to (0,m-1) using BFS. You can change it to fit variable points.

n,m,k1,k2=[int(i) for i in input().split()]
arr=[[int(j) for j in input().split()] for i in range(n)]
x=[[-1 for i in range(m)] for j in range(n)]
x[0][0]=0
vis={}
q=[(0,0)]
while len(q)!=0:
    curr=q[0]
    rem=q.pop(0)
    vis[curr]=True
    r=curr[0]
    c=curr[1]
    if r-1>=0 and arr[r-1][c]==0:
        if vis.get((r-1,c),-1)==-1 or vis[(r-1,c)]!=True:
            q.append((r-1,c))
            x[r-1][c]=x[r][c]+1
    if r+1<n and arr[r+1][c]==0:
        if vis.get((r+1,c),-1)==-1 or vis[(r+1,c)]!=True:
            q.append((r+1,c))
            x[r+1][c]=x[r][c]+1
    if c-1>=0 and arr[r][c-1]==0:
        if vis.get((r,c-1),-1)==-1 or vis[(r,c-1)]!=True:
            q.append((r,c-1))
            x[r][c-1]=x[r][c]+1
    if c+1<m and arr[r][c+1]==0:
        if vis.get((r,c+1),-1)==-1 or vis[(r,c+1)]!=True:
            q.append((r,c+1))
            x[r][c+1]=x[r][c]+1
    #for i in x:
        #print(i)
ans=x[0][m-1]
if ans==-1:
    print(-1)
else:
    print(ans)
  • input matrix should consist of 0's and 1's. 0 is for possible movement.
  • n is number of rows .
  • m is number of columns.
  • arr is the given matrix.
  • x is the distance matrix from (0,0).
  • vis is a dictionary giving a boolean if the node is visited.
  • output of -1 shows that there is no such path possible.
Apurv
  • 71
  • 8
0

Your grid forms a graph (or at least can be viewed as a graph). Eliminating some directions of movement indicates that it's a directed graph. If you can't move from one node to another at all, that's an edge that isn't present in the graph.

Once you've encoded your grid into graph form, it's a simple matter of selecting among the well-known graph algorithms (of which you're apparently already aware) to traverse it for the type of result you want (e.g. shortest path).

Edit: I've looked at the answer you posted, but I'm not sure what that code is supposed to be/do. Just for example, it has: if(y>=0) max(abs(x),y);. This doesn't seem (at least to me) to make much sense -- the result from the max is simply thrown away. To accomplish something useful, it needs to be returned or assigned or something on that order. As it stands, the best you can hope is that the compiler spots it as dead code, and doesn't generate anything for it.

My guess is that the code doesn't really work quite as intended, and if it does anything useful, it's more by accident than design. It would take a fair amount of time and effort to be sure you've sorted out problems like this to the point that you were really sure what it did, and even more difficult to guess what was really intended.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • please check the algorithm post it as an answer – Alan_AI Feb 22 '10 at 15:24
  • you are right about the line that doesn't do anything, i will redit my post and erase it, but i tried to write a main() function to test it and i was astonished that it could solve all inputs i entered including edge values.. i'm astonished – Alan_AI Feb 22 '10 at 16:13
  • I'm not sure how you're testing it -- based on the code by itself, it's not at all clear what format of input it expects. The result appears to be only a path length, with no information about what path it actually computed. In any case, a small amount of code producing correct results isn't particularly astonishing -- an exhaustive search is often pretty simple, just quite slow for large graphs. – Jerry Coffin Feb 22 '10 at 16:36
  • yes it only computes the length of the path, that's what i'm talking about, i'm not interested in the path itself... i really tested it, and many contestants on topcoder posted algorithms similar to this, that what excited me – Alan_AI Feb 22 '10 at 21:58
-3

use A* algorithm for finding the path between two points in a 2D grid. http://theory.stanford.edu/~amitp/GameProgramming/ImplementationNotes.html