簡體   English   中英

獲取Python中二維數組中單元格的最短路徑

[英]Get shortest path to a cell in a 2D array in Python

我有一個二維數組arr ,其中每個單元格的值都是 1、2 或 3,例如, arr[0][0] = 3, arr[2][1] = 2, and arr[0][4] = 1

我想知道從給定的某個單元格的最短路徑,例如, arr[5][5]到最近的單元格,其值為 2,其中路徑不應包含任何值為 1 的單元格。我該怎么做這個?

下面是BFS的腳本,但是我怎樣才能讓它接受一個二維數組作為圖形,並將起點作為數組中的某個單元格位置,然后從這個單元格轉到最近的兩個,避免使用 1s 的單元格,以便它看起來像bfs(2darray, starting location, 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')

在此處輸入圖片說明

您可以為此使用簡單的廣度優先搜索 基本上,網格中的每個單元格對應於圖中的一個節點,相鄰單元格之間有邊。 從起始位置開始,不斷擴大可通過的單元格,直到找到目標單元格。

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)]

如果列表不是太大,我找到的最簡單的解決方案是使用 NumPy 庫的where函數來查找具有您要查找的值的單元格。 因此,您需要將列表轉換為 NumPy 數組。

下面的代碼可能會被簡化以使其更短、更高效,但這樣會更清晰。 順便說一下,您可以計算兩種距離:典型的歐幾里得距離和曼哈頓距離。

如果在原始單元格的相同距離處有多個目標單元格,則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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM