获取二维数组python中单元格的最短路径

2024-05-14 17:03:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个二维数组arr,其中每个单元格都有一个值1、2或3,例如arr[0][0] = 3, arr[2][1] = 2 and arr[0][4] = 1。我想知道从给定单元格(例如arr[5][5])到最近的值为2的单元格(其中路径不应包含任何值为1的单元格)的最短路径。有什么建议吗?

下面是BFS的脚本,但我不知道如何让它接受2d数组作为图形,并以数组中的某个单元格位置作为起始点,然后从该单元格到最近的2,避开1的单元格,使其看起来像BFS(2darray,起始位置,2)?

def bfs(graph, start, end):
    # maintain a queue of paths
    queue = []
    # push the first path into the queue
    queue.append([start])
    while queue:
        # get the first path from the queue
        path = queue.pop(0)
        # get the last node from the path
        node = path[-1]
        # path found
        if node == end:
            return path
        # enumerate all adjacent nodes, construct a new path and push it into the queue
        for adjacent in graph.get(node, []):
            new_path = list(path)
            new_path.append(adjacent)
            queue.append(new_path)

print bfs(graph, '1', '11')

enter image description here


Tags: andthepath路径nodenewgetqueue
2条回答

如果列表不太大,我找到的最简单的解决方案是使用numpy库的where函数来查找具有您要查找的值的单元格。因此,您需要将列表转换为numpy数组。

下面的代码可能会被简化,以使其更简短、更高效,但这样会更清楚。顺便说一下,您可以计算两种距离:典型的欧几里德距离和manhattan

如果在与原始单元格相同的距离上有多个目标单元格,min_coords对应于找到的第一个单元格(先按行,然后按列)。

import numpy as np

# The list needs to be transformed into an array in order to use the np.where method
# arr = np.random.randint(5, size=(6, 6))
arr = np.array([[0, 0, 0, 1, 1, 3],
                [0, 0, 2, 1, 1, 0],
                [0, 0, 1, 1, 1, 1],
                [3, 0, 3, 1, 1, 1], ])

# Origin cell to make the search
x0, y0 = (1, 1)
targetValue = 3

# This is the keypoint of the problem: find the positions of the cells containing the searched value
positions = np.where(arr == targetValue)
x, y = positions

dx = abs(x0 - x)  # Horizontal distance
dy = abs(y0 - y)  # Vertical distance

# There are different criteria to compute distances
euclidean_distance = np.sqrt(dx ** 2 + dy ** 2)
manhattan_distance = abs(dx + dy)
my_distance = euclidean_distance  # Criterion choice
min_dist = min(my_distance)
print(min_dist)

min_pos = np.argmin(my_distance)  # This method will only return the first occurrence (!)
min_coords = x[min_pos], y[min_pos]
print(min_coords)

你可以用一个简单的breadth first search来完成这个。基本上,网格中的每个单元格都对应于图中的一个节点,相邻单元格之间有边。从起始位置开始,不断扩展可通过的单元格,直到找到目标单元格。

def bfs(grid, start):
    queue = collections.deque([[start]])
    seen = set([start])
    while queue:
        path = queue.popleft()
        x, y = path[-1]
        if grid[y][x] == goal:
            return path
        for x2, y2 in ((x+1,y), (x-1,y), (x,y+1), (x,y-1)):
            if 0 <= x2 < width and 0 <= y2 < height and grid[y2][x2] != wall and (x2, y2) not in seen:
                queue.append(path + [(x2, y2)])
                seen.add((x2, y2))

网格设置和结果:(请注意,我使用的是符号而不是数字,原因是这样更容易直观地分析网格并验证解决方案。)

wall, clear, goal = "#", ".", "*"
width, height = 10, 5
grid = ["..........",
        "..*#...##.",
        "..##...#*.",
        ".....###..",
        "......*..."]
path = bfs(grid, (5, 2))
# [(5, 2), (4, 2), (4, 3), (4, 4), (5, 4), (6, 4)]

相关问题 更多 >

    热门问题