OD C卷 - 亲子游戏

亲子游戏 (200)

  • 在一个二维矩阵(n*n)的格子地图上,宝宝和妈妈抽签决定各自的位置,每个格子有不同数量的糖果,部分格子有障碍物;
  • 游戏规则,妈妈必须在最短的时间(每次走一步)到达宝宝的位置,路上的糖果都可以拿走,不能走障碍物的格子,只能上下左右的走;
  • 妈妈在最短到达宝宝位置的时间内最多拿到多少糖果。
    输入描述:
    第一行输入n;
    后续n行,每行有n个值,-3表示妈妈,-2表示宝宝,-1表示障碍物,>=0表示糖果数,0没有糖果,但可以通过;
    输出描述:
    妈妈在最短到达宝宝位置的时间内最多拿到多少糖果,地图最大50*50;
    若无法到达宝宝位置,则输出-1

示例1
输入:
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3
输出:
9

示例2
输入:
4
3 2 1 -3
-1 -1 1 1
1 1 -1 2
-2 1 -1 3
输出:
-1

思路:

  • BFS/DFS
  • 先找最短路径(最少步子),在最短路径的情况下,再找最多糖果数;
  • 两次BFS

class MBGame:
    def solution(self, n, arr):
        self.visited = [[0 for j in range(n)] for i in range(n)]

        # 找妈妈的位置
        self.mother_pos = self.find_pos(n, arr, -3)

        # 找baby的位置
        self.baby_pos = self.find_pos(n, arr, -2)

        # 寻找最短路径(广度优先)
        steps = self.BFS(n)
        print("最短路径:", steps)

        # 计算在最短路径下的最大糖果数(走 steps 步)
        candy_arr = [[-1 for i in range(n)] for j in range(n)] # 不能用visited控制访问过程
        candy_arr[self.mother_pos[0]][self.mother_pos[1]] = 0 # 起始位置糖果数为0
        # 再次广度优先
        queue = [self.mother_pos]
        while True:
            if steps <= 0:
                break

            # 出队
            size = len(queue)
            for i in range(size):
                cur_pos = queue.pop(0)
                # 从当前格子走四个方向
                x, y = cur_pos
                directions = [(x, y + 1), (x, y - 1), (x - 1, y), (x + 1, y)]
                for new_x, new_y in directions:
                    # 新位置有效、不为-1、未走过,则可以走
                    if 0 <= new_x < n and 0 <= new_y < n and arr[new_x][new_y] != -1:
                        if candy_arr[new_x][new_y] == -1:
                            # 入队
                            queue.append((new_x, new_y))
                        # 更新新位置的糖果数
                        if arr[new_x][new_y] != -2: # 没到终点
                            candy_arr[new_x][new_y] = max(candy_arr[new_x][new_y],
                                                          candy_arr[x][y] + arr[new_x][new_y])
                        else: # 可以用2x2的 矩阵演示说明
                            candy_arr[new_x][new_y] = max(candy_arr[new_x][new_y],
                                                          candy_arr[x][y])
            steps -= 1
        for i in range(n):
            print("candy_arr:", candy_arr[i]) # 终点位置即为最大糖果数
        print(candy_arr[self.baby_pos[0]][self.baby_pos[1]])

    def BFS(self, n):
        # 起始点入队
        queue = []
        queue.append(self.mother_pos)

        # flag 标识是否能走到终点
        flag = False
        # 走的步子数
        steps = 0
        # 循环出队
        while True:
            size = len(queue)
            if size <= 0: # 判断队列是否为空
                break
            for i in range(size): # 当前层级的所有的位置,作为起始点(同时向外层走一步)
                start_pos = queue.pop(0)
                # 判断当前位置是否为终止位置
                x, y = start_pos
                if arr[x][y] == -2:
                    flag = True  # 走到终点,直接结束
                    break
                else:
                    # 从当前位置,开始走四个方向
                    directions = [(x, y+1), (x, y-1), (x-1, y), (x+1, y)]
                    for new_x, new_y in directions:
                        # 新位置有效、不为-1、未走过,则可以走
                        if 0 <= new_x < n and 0 <= new_y < n and arr[new_x][new_y] != -1 and \
                                self.visited[new_x][new_y] == 0:
                            self.visited[new_x][new_y] = 1 # 表示已走过
                            # 新位置入队
                            queue.append((new_x, new_y))
            if flag: # 走到终点,则提前终止外层循环
                break
            # 走一步
            steps += 1

        if not flag: # 无法到达终点
            return -1
        # 到达终点
        return steps # 第一个搜索到达的路径,一定是最短路径

    def find_pos(self, n, arr, val):
        for i in range(n):
            for j in range(n):
                if arr[i][j] == val:
                    m_pos = (i, j)
                    return m_pos


if __name__ == '__main__':
    mb_game = MBGame()
    # 3 2 1 -3
    # 1 -1 1 1
    # 1 1 -1 2
    # -2 1 2 3
    while True:
        try:
            n = int(input().strip())
            arr = []
            for i in range(n):
                arr.append(list(map(int, input().strip().split())))

            mb_game.solution(n, arr)
        except KeyboardInterrupt:
            break

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值