问题描述
此问题描述了在印刷电路板(PCB)上进行布线的需求,用网格表示 PCB。要求找到从 a
点到 b
点的最短路径,路径只能走直线或 L 形转弯(类似“日”字的路径),并且不能穿过障碍(灰色方块)。每走过一个格子,该格子就被锁定,其他路径不能通过。
解决思路
- 定义网格:创建一个表示 PCB 的网格,标记出
a
和b
的位置以及障碍物(用#
表示)。 - 移动约束:只能向上、下、左、右移动,并且路径只能以 L 形转弯。
- 广度优先搜索(BFS):使用 BFS 从
a
开始搜索到b
的路径,确保找到的路径是最短路径。 - 路径验证:确保路径不穿过任何障碍或被封锁的格子。
- 输出:打印最短路径的步数(如果存在)。
Python代码实现
from collections import deque
# 定义方向:上、下、左、右
DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
def is_valid(x, y, grid):
"""检查当前位置是否在边界内且未被阻挡。"""
return 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] != '#'
def find_shortest_path(grid, start, end):
m, n = len(grid), len(grid[0])
# 使用队列进行 BFS,记录 (x, y, 方向, 步数)
queue = deque([(start[0], start[1], -1, 0)])
# 记录访问过的格子和方向,避免重复访问
visited = set([(start[0], start[1], -1)])
while queue:
x, y, last_dir, steps = queue.popleft()
# 如果到达终点
if (x, y) == end:
return steps
# 遍历四个方向
for dir_index, (dx, dy) in enumerate(DIRECTIONS):
nx, ny = x + dx, y + dy
# L 形转弯限制:允许相同方向或直角方向
if dir_index != last_dir and last_dir != -1 and abs(dir_index - last_dir) % 2 == 0:
continue
# 检查新位置是否合法且未被访问
if is_valid(nx, ny, grid) and (nx, ny, dir_index) not in visited:
visited.add((nx, ny, dir_index))
queue.append((nx, ny, dir_index, steps + 1))
return -1 # 如果找不到路径,返回 -1
# 示例网格
grid = [
['.', '.', '.', '#', '.', '.', '.'],
['.', '#', '.', '.', '#', '.', '.'],
['.', '#', 'a', '.', '#', 'b', '.'],
['.', '#', '.', '.', '#', '.', '.'],
['.', '.', '.', '#', '.', '.', '.']
]
# 起点和终点
start = (2, 2) # a 的位置
end = (2, 5) # b 的位置
# 调用函数并打印结果
result = find_shortest_path(grid, start, end)
print("最短步数为:", result if result != -1 else "无可行路径")