📅  最后修改于: 2023-12-03 15:42:20.622000             🧑  作者: Mango
本次测验将涵盖以下内容:
这是一道关于门电路的问题。
给定一个 $N \times M$ 的门电路网格,其中 $1$ 表示门关闭,$0$ 表示门打开。
我们从网格的左上角 $(R_1, C_1)$ 出发,到达右下角 $(R_2, C_2)$ 时,如果网格上的门全部是打开的,那么我们就成功了。否则我们就失败了。
请你编写一个程序,判断是否能够成功通过这个电路网格。如果能够成功,则输出 "Yes",否则输出 "No"。
第一行包含两个整数 $N$ 和 $M$,表示网格的行数和列数。
接下来 $N$ 行,每行包含 $M$ 个整数 $0$ 或 $1$,表示电路网格。其中 $1$ 表示门关闭,$0$ 表示门打开。
接下来一行包含四个整数 $R_1$,$C_1$,$R_2$ 和 $C_2$,表示起点和终点的位置。
如果能够成功通过这个电路网格,则输出 "Yes",否则输出 "No"。
$2 \leq N, M \leq 100$
5 5
0 1 0 0 0
0 1 1 1 0
0 0 1 0 0
0 1 0 1 1
1 1 0 0 0
1 1 5 5
Yes
2 2
0 1
1 0
1 1 2 2
No
本题可以使用广度优先搜索(BFS)来解决,以下是BFS的代码模板。
from collections import deque
def bfs(start):
q = deque()
q.append(start)
while q:
node = q.popleft()
# do something
for nei in neighbors(node):
if nei not in visited:
visited.add(nei)
q.append(nei)
我们可以用这个模板来解决本题。
具体来说,我们首先使用 BFS 遍历整个有向图,然后在 BFS 的过程中,记录所有可以在终点位置之前到达的节点。最后,我们检查从起点位置有没有去往这些节点的边,以及这些节点到终点位置的边是否全部是开着的。
from collections import deque
n, m = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(n)]
r1, c1, r2, c2 = map(int, input().split())
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
def is_valid(x, y):
return 0 <= x < n and 0 <= y < m
def is_all_open(visited):
for x, y in visited:
if grid[x][y] == 1:
return False
return True
def bfs(start: tuple[int, int], end: tuple[int, int]) -> bool:
if start == end:
return True
q = deque()
q.append(start)
visited = set(start)
while q:
x, y = q.popleft()
for i in range(4):
nx, ny = x + dx[i], y + dy[i]
if not is_valid(nx, ny) or (nx, ny) in visited:
continue
if grid[nx][ny] == 1:
continue
visited.add((nx, ny))
q.append((nx, ny))
if (nx, ny) == end and is_all_open(visited):
return True
return False
if bfs((r1 - 1, c1 - 1), (r2 - 1, c2 - 1)):
print('Yes')
else:
print('No')
对于该题而言,BFS 的时间复杂度为 $O(NM)$,其中 $N$ 为网格的行数,$M$ 为网格的列数。因为我们最多只需要遍历网格中的每个点一次。