Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm to find the shortest path, with obstacles

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

like image 234
Valchris Avatar asked Mar 14 '11 19:03

Valchris


2 Answers

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!

like image 91
templatetypedef Avatar answered Oct 18 '22 01:10

templatetypedef


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;
}
like image 6
Dheeraj Sachan Avatar answered Oct 18 '22 03:10

Dheeraj Sachan