问题描述
我正在学习 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