使用规则从网格中查找路径

问题描述

我正在学习 bfs/dfs 并试图解决这个问题。 有一个 n × n 网格。找到在网格内从源单元格移动到目标单元格所需的路径(不一定是最短路径),并返回这些单元格之间的路径。每个网格单元格都有一个值。我们可以一次向所有四个方向移动:向上、向下、向左和向右。我们只能移动到具有相等或更小的值的相邻单元格。如果无法移动到达目标,则返回 None。 目标是右下角,起点左上角

input:
grid1 = [
[4,3,5],[2,3],2,1]
]

output:
[4,1] or [4,1]

以下是我的解决方案,但似乎结果与输出结果混合在一起。谁能帮帮我??

import collections
def findpath(grid):
    n = len(grid)
    seen = set()
    dirs = [(-1,0),(1,(0,1),-1)]
    res = []
    queue = collections.deque()
    queue.append((0,0))
    res.append(grid[0][0])
    while queue:
        i,j = queue.popleft()
        for x,y in dirs:
            new_i = x + i
            new_j = y + j
            if new_i<0 or new_i>=n or new_j<0 or new_j>=n or grid[new_i][new_j] > grid[i][j]:
                continue
            if (new_i,new_j) in seen:
                continue
            # print((new_i,new_j))
            # print(grid[new_i][new_j])
            res.append(grid[new_i][new_j])
            if new_i==n-1 and new_j == n-1:
                return res
            seen.add((new_i,new_j))
            queue.append((new_i,new_j))
    return None   
    

解决方法

因为我认为这是一个问题,递归是最简单的解决方案,我做了一个示例实现:

查找所有路径的函数:

def find_paths_recursive(grid,current_path=[(0,0)],solutions=[]):
    n = len(grid)
    dirs = [(-1,0),(1,(0,1),-1)]
    
    last_cell = current_path[-1]
    
    for x,y in dirs:
        new_i = last_cell[0] + x
        new_j = last_cell[1] + y
        
        # Check if new cell is in grid
        if new_i<0 or new_i>=n or new_j<0 or new_j>=n:
            continue
            
        # Check if new cell has bigger value than last
        if grid[new_i][new_j] > grid[last_cell[0]][last_cell[1]]:
            continue
        
        # Check if new cell is already in path
        if (new_i,new_j) in current_path:
            continue

        # Add cell to current path
        current_path_copy = current_path.copy()
        current_path_copy.append((new_i,new_j))

        if new_i==n-1 and new_j == n-1:
            solutions.append(current_path_copy)
        
        # Create new current_path array for every direction
        find_paths_recursive(grid,current_path_copy,solutions)
        
    return solutions

获取路径值的函数:

def compute_cell_values(grid1,solutions):
    path_values = []

    for solution in solutions:
        solution_values = []
        for cell in solution:
            solution_values.append(grid1[cell[0]][cell[1]])
        path_values.append(solution_values)
    return path_values

示例:

grid1 = [
[4,3,5],[2,3],2,1]
]


solutions = find_paths_recursive(grid1)
path_values = compute_cell_values(grid1,solutions)

print('Solutions:')
print(solutions)
print('Values:')
print(path_values)

示例输出:

Solutions:
[[(0,(2,2)],[(0,2),2)]]
Values:
[[4,1],[4,1]]

注意:重要的是,描述路径中单元格的值不是坐标,而是数组索引。这意味着单元格的第一个值是网格中的 y 值。

编辑:由于递归并不总是(或大部分不是)最好的解决方案,而且您对队列有一个好主意,我提出了另一个解决方案。您的解决方案的不同之处在于队列存储了我们探索的路径。它只返回一条路径(如果存在),但它是最短的。

def find_path(grid):
    n = len(grid)
    dirs = [(-1,-1)]
    queue = collections.deque()
    queue.append([(0,0)])
    
    while queue:
        current_path = queue.popleft()
        last_cell_i = current_path[-1][0]
        last_cell_j = current_path[-1][1]
        
        for x,y in dirs:
            new_i = x + last_cell_i
            new_j = y + last_cell_j
            
            # Check if new cell is in grid
            if new_i<0 or new_i>=n or new_j<0 or new_j>=n:
                continue
                
            # Check if new cell has bigger value than last
            if  grid[new_i][new_j] > grid[last_cell_i][last_cell_j]:
                continue
            
            # Check if new cell is already in path
            if (new_i,new_j) in current_path:
                continue
            
            # Add cell to current path
            current_path_copy = current_path.copy()
            current_path_copy.append((new_i,new_j))
        
            if new_i==n-1 and new_j == n-1:
                return current_path_copy
            
            queue.append(current_path_copy)
    return None