📜  门|门CS 2011 |第 64 题(1)

📅  最后修改于: 2023-12-03 15:42:22.663000             🧑  作者: Mango

题目描述

"门 | 门"是一款多人在线游戏,游戏场景是一个迷宫,玩家需要在迷宫中寻找出口。每个房间的门都有一个四位数的密码,玩家需要猜出密码才能通过门进入下一个房间。但是,玩家猜错了密码就会失去一定的生命值,生命值为0就会死亡,游戏结束。

现在需要你写一个小程序来模拟这个游戏,根据输入的迷宫地图和初始血量,输出玩家能否通关,以及通关时最小剩余血量是多少。

输入格式

输入的第一行包含两个整数 $m$ 和 $n$,表示迷宫的行数和列数。

接下来 $m$ 行,每行一个长度为 $n$ 的字符串,表示迷宫的地图。

地图中包含如下字符:

  • '.' 表示空地。
  • '#' 表示障碍物,不可通过。
  • 'S' 表示起点。
  • 'E' 表示终点。
  • '0'-'9' 表示密码锁,需要输入正确的密码才能通过。

输入保证有且仅有一个起点和终点,且输入格式正确。

输入中的数据,$1 \le m, n \le 50$,初始血量 $H_{0}$ 不超过 $10^4$。

输出格式

输出共两行:

  • 第一行一个整数,表示玩家能否通关。如果能够通关,输出 1,否则输出 0。
  • 第二行一个整数,表示通关时最小的剩余血量。
示例

输入1:

6 6
S..#..
.#.#.#
.#.#.#
.#.#.#
.#.#E#
....5.
10

输出1:

1
4

输入2:

5 5
S..#.
.###.
.#.##
...#.
.####
1

输出2:

0
1

解题思路

这是一道广度优先搜索的题目。我们可以利用队列进行广度优先搜索,找到从起点到终点的最短路径。

在搜索过程中需要维护两个状态,即当前走到的位置和当前的剩余生命值。我们需要注意的是,当遇到密码锁时,有两种决策:

  • 猜测密码,如果猜测错误,当前生命值减少。
  • 不猜测密码,消耗当前生命值通过门。

由于生命值可能会减少,因此我们需要使用一个二维数组来记录当前位置和当前生命值下,最小的剩余生命值。

参考代码

import heapq

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]


def bfs(maze, H, start_x, start_y, end_x, end_y, password):
    n = len(maze)
    m = len(maze[0])
    dis = [[10000 for j in range(m)] for i in range(n)]
    dis[start_x][start_y] = H
    q = [(0, start_x, start_y, H)]
    heapq.heapify(q)
  
    while len(q) > 0:
        d, x, y, h = heapq.heappop(q)
        if x == end_x and y == end_y:
            return True, h
        if d > dis[x][y]:
            continue
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx >= 0 and nx < n and ny >= 0 and ny < m:
                if maze[nx][ny] == '#':
                    continue
                if maze[nx][ny] == '.':
                    if h - 1 >= dis[nx][ny]:
                        dis[nx][ny] = h - 1
                        heapq.heappush(q, (d + 1, nx, ny, h - 1))
                if maze[nx][ny] in password:
                    p = int(maze[nx][ny])
                    if h - p >= dis[nx][ny]:
                        dis[nx][ny] = h - p
                        heapq.heappush(q, (d + 1, nx, ny, h - p))
    return False, 0


if __name__ == '__main__':
    n, m = map(int, input().split())
    maze = []
    for i in range(n):
        maze.append(input().strip())

    H = int(input().strip())

    password = '0123456789'
    start_x, start_y = 0, 0
    end_x, end_y = 0, 0
    for i in range(n):
        for j in range(m):
            if maze[i][j] == 'S':
                start_x, start_y = i, j
            elif maze[i][j] == 'E':
                end_x, end_y = i, j

    ok, ans = bfs(maze, H, start_x, start_y, end_x, end_y, password)
    if ok:
        print(1)
        print(ans)
    else:
        print(0)
        print(dis[end_x][end_y])

程序运行时,先读入输入的迷宫地图和初始血量,然后调用 bfs 函数来模拟游戏过程,并输出游戏结果。注意,在 bfs 函数中,需要使用 heapq 模块中的 heappushheappop 函数来维护搜索队列。