Python 华为OD試験問題 - 親子ゲーム

华为 OD 机试:亲子游戏

问题描述

母親と赤ちゃんが参加する親子ゲームがあります。N×N の2次元グリッドマップ上で、母親と赤ちゃん的位置を决めます。各セルには異なる数のキャンディーが入っており、一部のセルには障害物があります。

ゲームルールは、母親が最短時間で赤ちゃんの位置に到達する必要があります(各单位時間には1マスだけ移动できます)。道沿いのすべてのキャンディーを回収できます。障害物のセルは通行不可で、上下左右のみ移動可能です。

最短時間で赤ちゃんに到達する間に、最大で何個のキャンディーを回収できるかを出力してください(最短到達時間を优先し、その条件下で 최대한多くのキャンディーを得ることを优先します)。

输入格式

最初の一行目に N が与えられ、N は2次元矩阵のサイズを表します。 その後に N 行、各行に N の値があります。

值の説明:

  • -3:母親の位置
  • -2:赤ちゃんの位置
  • -1:障害物
  • >=0:キャンディーの数(0 はキャンディーがありませんが、通行可能です)

输出格式

母親が最短到达时间内に获取できる最多的糖果数を 출력します。行末に余分な空白はありません。

备注

マップのサイズは最大 50×50 です。

示例一

输入
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3
输出
9
说明

このマップには最短経路が2通りあります。緑色の線と黄色の線は両方とも最短距離6ステップですが、黄色の経路の方が多くのキャンディーを获取でき、9個になります。

示例二

输入
4
3 2 1 -3
-1 -1 1 1
1 1 -1 2
-2 1 -1 3
输出
-1
说明

このマップでは母親は赤ちゃんの位置に到達できません。

解题思路

最短路径の计算には BFS(幅優先探索)が适しています。难しいのは、最短路径の条件の下で最大のキャンディー数を计算することです。

BFS は层ごとに探索を行うため、まず各路径の長さを記録し、同じ长度の路径之间でキャンディー数の比较を行います。

题解

import collections

# グリッドのサイズ
grid_size = 4

# ゲームマップの定義
game_map = """
3 2 1 -3
1 -1 14 5
1 1 1 2
-2 1 2 3
""".strip()

# 文字列から2次元リストに変換
grid = [list(map(int, row.split())) for row in game_map.split('\n')]

# BFS 用キュー (行, 列, キャンディー数)
search_queue = collections.deque()

# 訪問済みフラグ
visited = [[False] * grid_size for _ in range(grid_size)]

# 母親の開始位置を探してキューに設定
start_row, start_col = 0, 0
for i in range(grid_size):
    for j in range(grid_size):
        if grid[i][j] == -3:
            start_row, start_col = i, j
            search_queue.append((start_row, start_col, 0))
            visited[start_row][start_col] = True

# 現在のタイムステップ
current_time = 0

# 結果リスト: [タイムステップ, キャンディー数]
valid_results = []

while search_queue:
    # 現在の層のキューサイズ
    level_size = len(search_queue)
    
    # 次の層のデータを一時保存
    next_level_items = []
    
    for _ in range(level_size):
        row, col, candy_count = search_queue.popleft()
        
        # 上下左右の移動方向
        for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            new_row, new_col = row + dr, col + dc
            
            # グリッド範囲内かつ障害物でないかつ未訪問
            if (0 <= new_row < grid_size and 
                0 <= new_col < grid_size and 
                grid[new_row][new_col] != -1 and 
                not visited[new_row][new_col]):
                
                # 赤ちゃんの位置に到達した場合
                if grid[new_row][new_col] == -2:
                    valid_results.append([current_time, candy_count])
                    break
                
                # 訪問済み标记
                visited[new_row][new_col] = True
                
                # 現在のキャンディー数を加えて次の层に追加
                cell_value = grid[new_row][new_col]
                next_level_items.append((new_row, new_col, candy_count + cell_value))
    
    # 現在の層の処理结束后、キャンディー数が多い顺に排序してキューに追加
    for item in sorted(next_level_items, key=lambda x: -x[2]):
        search_queue.append(item)
    
    # タイムステップを進める
    current_time += 1

#  결과 출력
if not valid_results:
    print(-1)
else:
    # 最小のタイムステップを見つける
    min_time = min(result[0] for result in valid_results)
    # そのタイムステップの中で最大のキャンディー数を見つける
    max_candies = max(result[1] for result in valid_results if result[0] == min_time)
    print(max_candies)

关键点说明

  1. BFS の层遍历:BFS を使用することで、从最短路径부터逐层探索 保证します。

  2. 同一时间内の最优选择:同しタイムステップ内で多个路径がある場合、キャンディー数が多いてなるように排序します。これにより、最短时间内で尽可能多くのキャンディーを获取できます。

  3. 访问控制:各セルは1回だけ访问し、二重探索を回避します。

  4. 结果选择:最後に、最短到达时间(最小タイムステップ)の中で最大のキャンディー数を出力します。到达できない场 합は -1 を出力します。

タグ: Python BFS 华为od 算法 广度优先搜索

8月1日 04:52 投稿