チャレンジ一覧に戻る
中級 0件解決済み 正答率0%

重み付きグリッド上の A* 探索

ゲームやロボットの経路探索を支える A* で、地形コストのグリッドを横切る最安の経路を求めます。

このチャレンジで学べること

  • 優先度付きキューで最安の経路を見つける
  • マンハッタン距離をヒューリスティックに使う
  • 許容的なヒューリスティックで最適性が保たれる理由を理解する

問題

原文(英語)を表示

A* はゲームやロボット工学で使われる代表的な経路探索アルゴリズムです。f = g + h の小さい順にセルを探索します。g はここまでに払ったコスト、h は残りのコストのヒューリスティックな見積もりです。

グリッドには各セルのコストが入っています。セルに入るとその値のコストがかかり、0 は入れない壁です。start から出発し (このセルのコストは払いません)、上下左右に移動できます。

ヒューリスティックとしてマンハッタン距離 |row - goal_row| + |col - goal_col| を使った A* を使ってください。通れるセルのコストはすべて 1 以上なので、このヒューリスティックは過大評価にならず、A* は最適な答えを返します。

a_star_cost(grid, start, goal) を実装してください。

入力

grid: セルのコストの行列 (0 = 壁)。

start, goal: [row, col] 形式の位置。

出力

goal に到達する最小の合計コストを返します。到達できない場合 (start または goal が壁の場合を含む) は -1 を返します。

制約

1 ≤ 行数, 列数 ≤ 100

0 ≤ 各コスト ≤ 9

例

例 1
入力:
goal = [2, 2]
grid = [
    [1, 1, 1],
    [1, 0, 1],
    [1, 1, 1]
]
start = [0, 0]

期待される出力:
expected = 4
入力:
std::vector<long long> goal = {2, 2};
std::vector<std::vector<long long>> grid = {
    {1, 1, 1},
    {1, 0, 1},
    {1, 1, 1}
};
std::vector<long long> start = {0, 0};

期待される出力:
long long expected = 4;
入力:
long[] goal = new long[] {2, 2};
long[][] grid = new long[][] {
    new long[] {1, 1, 1},
    new long[] {1, 0, 1},
    new long[] {1, 1, 1}
};
long[] start = new long[] {0, 0};

期待される出力:
long expected = 4;

解説

中央は壁です。右に 2 回、下に 2 回 (または下から右) 進むとコスト 1 のセルに 4 回入るので、合計 4 です。

例 2
入力:
goal = [0, 2]
grid = [
    [1, 9, 1],
    [1, 9, 1],
    [1, 1, 1]
]
start = [0, 0]

期待される出力:
expected = 6
入力:
std::vector<long long> goal = {0, 2};
std::vector<std::vector<long long>> grid = {
    {1, 9, 1},
    {1, 9, 1},
    {1, 1, 1}
};
std::vector<long long> start = {0, 0};

期待される出力:
long long expected = 6;
入力:
long[] goal = new long[] {0, 2};
long[][] grid = new long[][] {
    new long[] {1, 9, 1},
    new long[] {1, 9, 1},
    new long[] {1, 1, 1}
};
long[] start = new long[] {0, 0};

期待される出力:
long expected = 6;

解説

9 をまっすぐ横切ると 9 + 1 = 10 かかります。下に降りて最下行を進み、また上がるとコスト 1 のセルに 6 回入るので、合計 6 です。

解き方のヒント

まずは自分で考えてから、ヒントを 1 つずつ開いてみましょう。

ヒント 1

移動コストとゴールまでの Manhattan 距離の合計で優先順位付けする priority queue を使います。

ヒント 2

各 cell についてこれまでの最良コストを記録し、この経路で改善したときだけその cell を展開します。

ヒント 3

壁や、開始セルまたはゴールセルが塞がれている場合は不可能として扱い、開始セルに入るコストは 0 だと覚えておきます。

目安の計算量

時間 O(rows * cols log(rows * cols))、追加メモリ O(rows * cols)

参考資料

この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。

他の人の解答から学ぶ

コミュニティの解答

まだ公開された解答がありません。この課題を解いて最初の解答を共有しましょう。