12

I have a collection of Points which represents a grid, I'm looking for an algorithm that gets me the shortest distance between point A and B. The catch being any point (excluding A and B) can have an obstacle obstructing the path, and thus must be detoured. The path may not move in diagonals.

For anyone else looking to solve this type of problem, I found these references to be very useful:

http://optlab-server.sce.carleton.ca/POAnimations2007/DijkstrasAlgo.html

http://en.literateprograms.org/Dijkstra%27s_algorithm_%28Java%29#chunk%20def:visit%20each%20vertex%20u,%20always%20visiting%20vertex%20with%20smallest%20minDistance%20first

Valchris
  • 1,451
  • 2
  • 14
  • 33

2 Answers2

25

This is an excellent spot to use the A* search algorithm, a heuristic search algorithm that finds optimal paths between points very quickly even when there are obstacles present. The idea is to convert the grid into a graph where each cell in the grid is a node and in which there is an edge between any two adjacent cells that aren't obstructed from one another. Once you have this graph, the answer you're looking for is the shortest path in the graph from the start node to the destination node.

In order to use A*, you'll need a heuristic function that "guesses" the distance from any point on the grid to the destination square. One good heuristic for this would be to use the Manhattan distance between the two points.

If you're looking for an easier but still extremely efficient algorithm for finding the shortest path, consider looking into Dijkstra's algorithm, which can be thought of as a simpler version of A*. It's a bit slower than A*, but still runs extremely quickly and guarantees an optimal answer.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • @Valchris- Best of luck coding those up! Dijkstra's and A* are classic algorithms that can be used to solve all sorts of problems, and it's definitely worth knowing how to code them up. – templatetypedef Mar 14 '11 at 19:47
  • 1
    A* will always have a special place in my heart because the search will in the worst case devolve into a breadth first search, a nice fail-safe. – AndyG Mar 14 '11 at 23:58
  • is there an alternative if i need the shortest path around an obstacle? A* needs the map to be splitted in a grid and my vehicle will move on a zigzag way around the obstacle instead of a direct line – wutzebaer Jul 20 '15 at 23:14
  • @wutzebaer The general version of A* doesn't require you to use a grid, though it's often presented that way in tutorials. Are you familiar with directed and undirected graphs? – templatetypedef Jul 20 '15 at 23:18
  • hm i think so - ok i could create waypoints on all obstacle-edges and the target point, and then i can connect all points which connection does not touch any obstacle ... something like this? – wutzebaer Jul 20 '15 at 23:24
  • @wutzebaer That works. You can also discretize the space by creating a fine grid and dropping it on top of the world, or by sampling random points and connecting them if they don't pass through an obstacle. – templatetypedef Jul 20 '15 at 23:26
  • @templatetypedef that leads again to a zigzag route ... but with a fine enough grid it could lead to an interesting result (even when it leads to more collision-checks), thanks! ... – wutzebaer Jul 20 '15 at 23:32
6

This is a simple problem that can be solved using Breadth First Search

 /**
  * computing distance of each cell from the starting cell 
  * avoiding obstacles, 0 represents obstacle 1 represents non obstacle
  * we can take only one step x-1;x+1;y-1;y+1
 */

#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;

class XY
{
 public :
 int x;
int y;
};

int main()
{
int grid[8][8] = {
    {1,1,1,1,1,1,1,1},
    {1,0,0,0,1,1,1,1},
    {1,1,0,0,1,1,1,1},
    {1,1,0,0,1,1,1,1},
    {1,1,1,2,0,1,0,0},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1}
};


int rows = 8;
int cols = 8;

int distance[rows][cols];

for(int m = 0;m<rows;m++)
{
    for(int n =0;n<cols;n++)
    {
        distance[m][n] = -1;
    }
}

queue<XY> iterator;


XY xy;
xy.x = 0;
xy.y = 0;
distance[0][0] = 0;
iterator.push(xy);

while(!iterator.empty())
{
    xy = iterator.front();
    iterator.pop();
    //printf("popped %d+%d\n",xy.x ,xy.y);
    for(int p = -1;p<2;p++)
    {
        for(int q = -1;q<2;q++)
        {
            if(p == q)continue;
            int i = xy.x + p;
            int j = xy.y + q;

            if(i<0)i=0;
            if(j<0)j=0;
            if(i>rows-1)i=rows-1;
            if(j>cols-1)j=cols-1;

            if(i== xy.x && j == xy.y)continue;

    //              printf("i,j = %d,%d\n",i,j);

            if(distance[i][j] == -1)
            {
     //                 printf("******\n");
                if(grid[i][j] != 0)
                {
     //                 printf("assigned distance %d to %d+%d\n",distance[xy.x][xy.y] + 1,i,i); 
                distance[i][j] = distance[xy.x][xy.y] + 1;
                XY xyn;
                xyn.x = i;
                xyn.y = j;  
                iterator.push(xyn);
      //                    printf("pushed %d+%d\n",xyn.x,xyn.y);
                }
            }

        }
    }
}

for(int x = 0;x<rows;x++)
{
    for(int y =0;y<cols;y++)
    {
        printf("%d ",distance[x][y]);   
    }
    printf("\n");
}
return 0;
}
Dheeraj Sachan
  • 3,965
  • 2
  • 17
  • 18
  • 1
    this algorithm finds the shortest distance but not the actual path from source to destination. please correct me if i'm wrong. – Niko Aug 11 '21 at 22:11