Zurück zu den Herausforderungen
Mittel 0 gelöst 0% Erfolgsquote

A*-Suche auf einem gewichteten Gitter

Finde mit A*, dem Suchalgorithmus hinter der Wegfindung in Spielen und Robotern, den günstigsten Weg durch ein Gitter aus Geländekosten.

Das lernst du

  • Den günstigsten Weg mit einer Prioritätswarteschlange finden
  • Den Manhattan-Abstand als Heuristik nutzen
  • Verstehen, warum zulässige Heuristiken optimal bleiben

Problem

A* ist der klassische Wegfindungsalgorithmus in Spielen und Robotik. Er untersucht Zellen in der Reihenfolge von f = g + h, wobei g die bisher bezahlten Kosten sind und h eine heuristische Schätzung der noch verbleibenden Kosten.

Das Gitter enthält Kosten für jede Zelle: Das Betreten einer Zelle kostet ihren Wert, und 0 ist eine Wand, die nicht betreten werden kann. Du startest auf start (dessen Kosten werden nicht bezahlt) und darfst dich nach oben, unten, links oder rechts bewegen.

Verwende A* mit der Manhattan-Distanz |row - goal_row| + |col - goal_col| als Heuristik. Jede offene Zelle kostet mindestens 1, also überschätzt diese Heuristik nie und A* liefert eine optimale Antwort.

Implementiere a_star_cost(grid, start, goal).

Eingabe

grid: Eine Matrix der Zellkosten (0 = Wand).

start, goal: Positionen als [row, col].

Ausgabe

Gib die minimalen Gesamtkosten bis goal zurück, oder -1, wenn das Ziel nicht erreichbar ist (auch wenn start oder goal eine Wand ist).

Einschränkungen

1 ≤ Zeilen, Spalten ≤ 100

0 ≤ jede Kosten ≤ 9

Beispiele

Beispiel 1
Eingabe:
goal = [2, 2]
grid = [
    [1, 1, 1],
    [1, 0, 1],
    [1, 1, 1]
]
start = [0, 0]

Erwartete Ausgabe:
expected = 4
Eingabe:
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};

Erwartete Ausgabe:
long long expected = 4;
Eingabe:
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};

Erwartete Ausgabe:
long expected = 4;

Erläuterung

Die Mitte ist eine Wand. Zweimal nach rechts und zweimal nach unten (oder erst nach unten, dann nach rechts) betritt 4 Zellen mit Kosten 1, insgesamt 4.

Beispiel 2
Eingabe:
goal = [0, 2]
grid = [
    [1, 9, 1],
    [1, 9, 1],
    [1, 1, 1]
]
start = [0, 0]

Erwartete Ausgabe:
expected = 6
Eingabe:
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};

Erwartete Ausgabe:
long long expected = 6;
Eingabe:
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};

Erwartete Ausgabe:
long expected = 6;

Erläuterung

Die 9 direkt zu überqueren kostet 9 + 1 = 10. Nach unten, entlang der untersten Zeile und wieder nach oben betritt sechs Zellen mit Kosten 1, insgesamt 6.

So gehst du vor

Versuch es zuerst allein und öffne dann einen Hinweis nach dem anderen.

Hinweis 1

Verwende eine Prioritätswarteschlange, die nach bisher zurückgelegten Kosten plus Manhattan-Distanz zum Ziel sortiert ist.

Hinweis 2

Verfolge die bisher beste gefundene Kosten für jede Zelle und expandiere eine Zelle nur, wenn dieser Pfad sie verbessert.

Hinweis 3

Behandle Wände sowie blockierte Start- oder Zielzellen als unmöglich, und vergiss nicht, dass das Betreten der Startzelle kostenlos ist.

Erwartete Komplexität

Zeit O(rows * cols log(rows * cols)), zusätzlicher Speicher O(rows * cols)

Referenzen

Diese Aufgabe wurde für CodeUtility angepasst. Beachte die oben genannten Vorgaben und Einschränkungen.

Von anderen lernen

Community-Lösungen

Noch keine veröffentlichten Lösungen. Löse die Aufgabe und teile als Erster eine Lösung.