首页 > 试题广场 >

走迷宫

[编程题]走迷宫
  • 热度指数:15289 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}给定一个 n \times m 的网格。你从起点 (x_s, y_s) 出发,每一次可以向上、下、左、右移动一步(若不超出边界)。某些格子上存在障碍物,无法经过。求从 (x_s, y_s) 移动到终点 (x_t, y_t) 的最少步数;若无法到达,输出 -1

输入描述:
\hspace{15pt}在一行上输入两个整数 n, m \left(1 \leqq n, m \leqq 1000\right),代表网格的行数与列数。
\hspace{15pt}在一行上输入四个整数 x_s, y_s, x_t, y_t \left(1 \leqq x_s, x_t \leqq n;\ 1 \leqq y_s, y_t \leqq m\right),代表起点与终点的坐标。
\hspace{15pt}此后 n 行,第 i 行输入一个长度为 m 的字符串 g_i,其中
\hspace{23pt}\bullet\,g_{i, j}=\texttt{,表示第 i 行第 j 列为障碍物;
\hspace{23pt}\bullet\,g_{i, j}=\texttt{,表示该格子可通行。
\hspace{15pt}保证起点所在格子可通行。


输出描述:
\hspace{15pt}输出一个整数,表示最少移动次数;若无法到达,输出 -1
示例1

输入

5 5
1 1 5 5
.....
****.
.....
**.**
.....

输出

12
示例2

输入

5 5
1 1 4 5
.....
****.
.....
**.**
.....

输出

-1
示例3

输入

5 5
1 1 5 5
.....
****.
.....
*****
.....

输出

-1
from collections import deque
class Maze:
    def __init__(self):
        self.n, self.m = list(map(int, input().split(" ")))
        self.start_y, self.start_x, self.end_y, self.end_x = list(
            map(lambda x: int(x)-1, input().split(" ")))
        self.grid = [['\0' for _ in range(self.m)]
                     for _ in range(self.n)]
        for i in range(self.n):
            self.grid[i] = list(str(input()))
        self.visited = [[False for _ in range(self.m)]
                        for _ in range(self.n)]
        self.direction = [(1, 0), (0, 1), (-1, 0), (0, -1)]
    def bfs(self):
        queue = deque([(self.start_x, self.start_y, 0)])
        while queue:
            curr_x, curr_y, curr_len = queue.popleft()
            if self.visited[curr_y][curr_x]:
                continue
            self.visited[curr_y][curr_x] = True
            if (curr_y, curr_x) == (self.end_y, self.end_x):
                return curr_len
            for dx, dy in self.direction:
                nx = curr_x + dx
                ny = curr_y + dy
                if ((0 <= nx < self.m) and
                    (0 <= ny < self.n) and
                        self.grid[ny][nx] == "." and
                        not self.visited[ny][nx]):
                    nl = curr_len+1
                    queue.append((nx, ny, nl))
        return -1
if __name__ == "__main__":
    m = Maze()
    print(m.bfs())
发表于 2025-10-10 09:15:10 回复(0)
from collections import deque

n,m = map(int , input().split())
xs,ys,xt,yt = map(int, input().split())
xs,ys,xt,yt = xs-1,ys-1,xt-1,yt-1
maze = []
for _ in range(n):
    row = list(input())
    maze.append(row)

def play_maze(n,m,xs,ys,xt,yt,maze):
    visited= [[False]*m for _ in range(n)]
    visited[xs][ys]=True
    q = deque()
    q.append((xs,ys,0)) # x,y,steps
    directions = [(1,0),(-1,0),(0,1),(0,-1)]
    while q:
        x,y,steps = q.popleft()
        if (x,y)==(xt,yt):
            return steps
        for dx,dy in directions:
            nx ,ny = x+dx, y+dy
            if 0<=nx<n and 0<=ny<m and maze[nx][ny]=='.' and not visited[nx][ny]:
                visited[nx][ny]=True
                # 注意这里不能写steps +=1,再append(steps),会导致不同方向之间的初始steps会不同
                q.append((nx,ny,steps+1))
    return -1

print(play_maze(n,m,xs,ys,xt,yt,maze)) 

发表于 2025-08-14 15:17:53 回复(0)
import sys
from collections import deque


def main():
    n, m = map(int, sys.stdin.readline().split())
    xs, ys, xt, yt = map(int, sys.stdin.readline().split())
    grid = [sys.stdin.readline().strip() for _ in range(n)]

    # 转换为 0-based 或保持 1-based,根据题目要求调整
    xs -= 1
    ys -= 1
    xt -= 1
    yt -= 1

    if grid[xs][ys] == "*"&nbs***bsp;grid[xt][yt] == "*":
        print(-1)
        return

    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    visited = [[-1 for _ in range(m)] for __ in range(n)]
    q = deque()
    q.append((xs, ys))
    visited[xs][ys] = 0

    while q:
        x, y = q.popleft()
        if x == xt and y == yt:
            print(visited[x][y])
            return
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if (
                0 <= nx < n
                and 0 <= ny < m
                and grid[nx][ny] == "."
                and visited[nx][ny] == -1
            ):
                visited[nx][ny] = visited[x][y] + 1
                q.append((nx, ny))

    print(-1)


if __name__ == "__main__":
    main()

发表于 2025-06-21 15:17:40 回复(0)
也出现了爆内存问题,因为每一次visit点的时候要标记为visited,否则会重复访问,导致队列膨胀;其中visited的标记也可以使用dictionary,但更耗内存,因为要格外存储哈希值,value等元素;另外,存储grid的时候可以将符号改成true/false,或者改成0-based索引(从0开始是第一位),更加节省内存空间;这道题因为是单点到单点的最短距离,bfs更适合。

import sys
from collections import deque

def bfs(n,m,xs,ys,xt,yt, grid):
queue = deque()
visited = [[False for _ in range(m+1)] for _ in range(n+1)]
queue.append((xs,ys,0)) #初始化visited的点,也可以用dictionary
visited[xs][ys] = True

direction = [(-1,0),(1,0),(0,1),(0,-1)]

while queue:
u,v,w = queue.popleft()

if (u,v) == (xt,yt): #找到想要的点
return w

for i in direction: #遍历和当前点相连的点
(nextx,nexty) = (u+i[0], v+i[1])

if 1<= nextx <= n and 1<= nexty <= m and visited[nextx][nexty] == False and grid[nextx][nexty] == '.':
#需要标记visited,否则会爆内存
visited[nextx][nexty] = True
queue.append((nextx,nexty,w+1))
return -1

n, m = map(int, sys.stdin.readline().split())
xs, ys, xt, yt = map(int, sys.stdin.readline().split())
grid = [''] * (n + 1) # 1-based索引
for i in range(1, n + 1):
# 1-based索引,每一个grid的string list第一位为空
grid[i] = ' '+sys.stdin.readline().strip()

step = bfs(n,m,xs,ys,xt,yt, grid)
print(step)

发表于 2025-05-18 02:43:01 回复(0)
n,m = map(int,input().split())
x0,y0,xend,yend = map(lambda x:int(x) - 1,input().split())
start = (x0,y0)
end = (xend,yend)
g = [list(input()) for _ in range(n)]
# print(g,start,end)
###############
from collections import deque
q = deque([(x0,y0,0)])

if g[x0][y0] == "*" or g[xend][yend] == "*":
    print(-1)
else:
    found = 0
    while q:
        x,y,d = q.popleft()
        if (x,y) == (xend,yend):
            print(d)
            found = 1
            break
        directions = [(1,0),(0,1),(0,-1),(-1,0)]
        for dx,dy in directions:
            x_next,y_next = x + dx, y + dy
            if x_next < 0 or x_next >= n or y_next < 0 or y_next >= m or g[x_next][y_next] == "*":
                continue
            q.append((x_next,y_next,d+1))
            g[x_next][y_next] = "*"
    if not found:
        print(-1)

           
       

发表于 2025-05-14 11:00:37 回复(0)
这个题目说好的起点不存在障碍物,结果最后一个实例起点就有障碍物,害我想了半天,另外的本题尽量使用bfs
from copy import copy
import copy
def bfs(a1,b1,a2,b2,pathmap):
    queue=[[a1,b1]]
    step=0
    while queue:
        queue1=[]
        for item in queue:
            for i, j in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
                if (0<=item[0]+i<=len(pathmap)-1)&(0<=item[1]+j<=len(pathmap[0])-1):
                    a=item[0]+i;b=item[1]+j
                    if (pathmap[a][b]!=1)&(pathmap[a][b]!=-1):
                        queue1.append([a,b])
                        pathmap[a][b]=1
                    if (a==a2)&(b==b2):
                        return step+1

        step+=1
        queue=copy.deepcopy(queue1)
    return -1

n,m=map(int,input().split())
a1,b1,a2,b2=map(int,input().split())
map=[]
for _ in range(n):
    map.append(list(input()))
pathmap=[]
for i in range(n):
    temp=[]
    for j in range(m):
        if map[i][j]=='.':
            temp.append(0)
        else:
            temp.append(-1)
    pathmap.append(temp)

if (pathmap[a2-1][b2-1]==-1)|(pathmap[a1-1][b1-1]==-1):
    short=-1
else:
    pathmap[a1 - 1][b1 - 1] = 1
    short=bfs(a1-1,b1-1,a2-1,b2-1,pathmap)
print(short)

发表于 2024-11-26 15:04:08 回复(0)
import sys

'''
获取数据,行列
'''

s = input()
L =s.split()
n,m  = int(L[0]),int(L[1])
L2=input().split()

def InitMapAndDistance(s,L,n,m):
    '''
        获取坐标
    '''
    

    #L3用来存储地图
    #i的范围小于行数,可以循环接收n行的数据
    #s中不是以空格分隔的,需要用list函数将s转化为列表
    #将s中的符号转化为0和1存储到地图中
    L3=[]
    i=1
    dict1={}
    while i<=n:
    
        s=list(input())
        L4=[]   
        for x in range(len(s)):
            if s[x]==".":
                L4.append(0)
            else:
                dict1[i]=x
                L4.append(1)
        L3.append(L4)
    #while循环中改变循环变量
        i+=1
    return L3,dict1



def search(a,b,n,m,L3,dict1):
    #L4存储距离,初始化一个距离用的二维列表
    L4=[[0 for i in range(m)] for i in range(n)]


    #定义四个方向
    directionsx=[0,1,0,-1]
    directionsy=[-1,0,1,0]


    #初始化搜索的起点
    queue =[]
    queue.append([a,b])
    L4[a][b]=0


    while queue:
        q=queue.pop(0)
    #使用for语句控制循环次数四次,广度搜索上下左右四个方向
        for k in range(4):
            i,j=q[0],q[1]
            L3[i][j]=1
            x=i+directionsx[k]
            y=j+directionsy[k]
            if x in dict1.keys() and  dict1[x]==y:
                pass
            if 0<=x<n and 0<=y <m:
                if L3[x][y]==0:
                    queue.append([x,y])
                    L4[x][y]=L4[i][j]+1
    return L4
        



def Caculatedistance():
    xs,ys,xt,yt=int(L2[0]),int(L2[1]),int(L2[2]),(int(L2[3]))
    L3,dict1 = InitMapAndDistance(s,L,n,m)
    L4 = search(xs-1,ys-1,n,m,L3,dict1)
    if L4[xt-1][yt-1]==0:
        print(-1)
    else:
        print(L4[xt-1][yt-1])


Caculatedistance()









发表于 2023-03-05 15:11:25 回复(0)