Skip to content

19930: 寻宝

bfs, http://cs101.openjudge.cn/practice/19930

Billy获得了一张藏宝图,图上标记了普通点(0),藏宝点(1)和陷阱(2)。按照藏宝图,Billy只能上下左右移动,每次移动一格,且途中不能经过陷阱。现在Billy从藏宝图的左上角出发,请问他是否能到达藏宝点?如果能,所需最短步数为多少?

输入

第一行为两个整数m,n,分别表示藏宝图的行数和列数。(m<=50,n<=50) 此后m行,每行n个整数(0,1,2),表示藏宝图的内容。

输出

如果不能到达,输出‘NO’。 如果能到达,输出所需的最短步数(一个整数)。

样例输入

样例输入1:
3 4
0 0 2 0
0 2 1 0
0 0 0 0

样例输出1:
5

样例输出

样例输入2:
2 2
0 2
2 1

样例输出2:
NO

提示

每张藏宝图有且仅有一个藏宝点。 输入保证左上角(起点)不是陷阱。

来源:by cs101-2009 邵天泽

其实所有求最短、最长的问题都能用heapq实现,在图搜索中搭配bfs尤其好用。

python
#23 工学院 苏王捷
import heapq
def bfs(x,y):
    d=[[-1,0],[1,0],[0,1],[0,-1]]
    queue=[]
    heapq.heappush(queue,[0,x,y])
    check=set()
    check.add((x,y))
    while queue:
        step,x,y=map(int,heapq.heappop(queue))
        if martix[x][y]==1:
            return step
        for i in range(4):
            dx,dy=x+d[i][0],y+d[i][1]
            if martix[dx][dy]!=2 and (dx,dy) not in check:
                heapq.heappush(queue,[step+1,dx,dy])
                check.add((dx,dy))
    return "NO"
            
m,n=map(int,input().split())
martix=[[2]*(n+2)]+[[2]+list(map(int,input().split()))+[2] for i in range(m)]+[[2]*(n+2)]
print(bfs(1,1))

找最短路径,是bfs,借助队列queue实现,head和tail分别指向队列的头和尾。

python
q = []

step = [[0, 1], [1, 0], [-1, 0], [0, -1]]
vis = [[0] * 52 for _ in range(52)]
g = []

m, n = map(int, input().split())
for i in range(m):
    g.append([int(x) for x in input().split()])

def check(x, y):
    if (x < 0 or y < 0 or x >= m or y >= n):
        return False
    if (vis[x][y] or g[x][y] == 2):
        return False
    return True


q.append((0, 0))
head = 0
tail = 1
level = 0
while (head < tail):
    # i = head
    # j = tail
    for k in range(head, tail):
        x, y = q[head]
        head += 1
        if (g[x][y] == 1):
            print(level)
            exit(0)     
        for z in range(4):
            newx = x + step[z][0]
            newy = y + step[z][1]
            if (check(newx, newy)):
                vis[newx][newy] = 1
                q.append((newx, newy))
                tail += 1
    level += 1
print('NO')