找到最短路径的算法,有障碍物

时间:2011-03-14 19:38:45

标签: java algorithm pathing

我有一个代表网格的点集合,我正在寻找一种能让我获得A点和B点之间最短距离的算法。 任何点(不包括A和B)的捕获物都可能有阻碍路径的障碍物,因此必须绕道而行。路径可能不会以对角线移动。

对于任何想要解决此类问题的人,我发现这些引用非常有用:

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

3 个答案:

答案 0 :(得分:19)

这是使用A* search algorithm的绝佳位置,graph是一种启发式搜索算法,即使存在障碍物,也可以非常快速地找到点之间的最佳路径。想法是将网格转换为the Manhattan distance,其中网格中的每个单元格是节点,并且在任何两个相邻单元格之间存在边缘,这些边缘彼此不受阻碍。获得此图表后,您要查找的答案是图表中从起始节点到目标节点的最短路径。

为了使用A *,您需要一个启发式功能,“猜测”从网格上任意点到目标方块的距离。一个好的启发式方法是在两点之间使用Dijkstra's algorithm

如果您正在寻找一种更简单但仍然非常有效的查找最短路径的算法,请考虑查看{{3}},这可以被认为是A *的更简单版本。它比A *慢一点,但仍能非常快速地运行并保证最佳答案。

希望这有帮助!

答案 1 :(得分:3)

这是一个可以使用广度优先搜索

解决的简单问题
 /**
  * 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;
}

答案 2 :(得分:0)

我相信可以通过前面提到的广度优先搜索(BFS)来解决给定的问题。建立问题陈述很重要。因此,让我们描述问题,然后转到问题的解决部分。

问题描述:

您负责为其中一个准备最近购买的批次 新建筑。地上布满战es,有一个障碍 需要先将其取下,然后才能为建筑物准备基础。 拆除机器人必须先清除障碍物,然后才能继续前进。 建筑物。 编写算法来确定所需的最小距离 拆除机器人以清除障碍物。

假设:

  1. 除了沟槽,地块是平坦的,可以表示为2D网格。
  2. 拆除机器人必须从批次的左上角开始 始终保持平坦,可以一次向上,向下,向右或向左移动一个方块。
  3. 拆除机器人无法进入战and,也不能离开地段。
  4. 平坦区域表示为1,沟槽表示为0的区域, 阻碍了9。

输出:

返回一个整数,该整数表示要删除的最小距离 障碍物返回-1。

解决方案

from collections import defaultdict

from collections import deque


def is_valid(i, j, m, n, matrix, visited):
    if i >= 0 and j >= 0 \
            and i < m and j < n \
            and visited[i][j] is False \
            and matrix[i][j] in (1, 9):
        return True

    return False


def remove_obstacle(matrix, m, n):
    queue = deque()
    i = 0
    j = 0
    queue.append((i, j, 0))

    visited = [[False for _ in range(n)] for _ in range(m)]
    distance_matrix = [[100 for _ in range(n)] for _ in range(m)]

    visited[i][j] = True

    while queue:
        i, j, distance = queue.popleft()
        distance_matrix[i][j] = distance

        visited[i][j] = True

        if matrix[i][j] == 9:
            return distance
        new_distance = distance + 1
        if is_valid(i + 1, j, m, n, matrix, visited):
            queue.append((i + 1, j, new_distance))

        if is_valid(i - 1, j, m, n, matrix, visited):
            queue.append((i - 1, j, new_distance))

        if is_valid(i, j + 1, m, n, matrix, visited):
            queue.append((i, j + 1, new_distance))

        if is_valid(i, j - 1, m, n, matrix, visited):
            queue.append((i, j - 1, new_distance))

    return -1


if __name__ == '__main__':
    m = 5
    n = 4
    l = [
        [1, 1, 1, 1],
        [0, 1, 1, 1],
        [0, 1, 0, 1],
        [1, 1, 9, 1],
        [0, 0, 1, 1]
    ]

    bfs = remove_obstacle(l, m, n)
    assert bfs == 5

    m = 3
    n = 3
    l = [
        [1, 0, 0],
        [1, 0, 0],
        [1, 9, 1]
    ]

    bfs = remove_obstacle(l, m, n)
    assert bfs == 3