A*探索アルゴリズム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Nな人

A*探索アルゴリズム

#1

投稿記事 by Nな人 » 6年前

お初にお目にかかります。
アルゴリズムのことで質問をさせていただける場所を探していると、
こちらが良いと教えていただいたのでスレッドを建てさせていただきました。

今回、迷路を自動で解くプログラムを作成しているのですが、
その際に最短ルートを求めたいと思い、いろいろ調べていると、
A*探索アルゴリズムというものを見つけ、それを使ってみようと思っているのですが、
難しくなかなか理解ができません。

様々なサイト様をめぐって、
「スタート地点から自分が今いる地点の距離と、自分が今いる地点からゴール地点までの距離を足しあわせて考えていく」
ということは分かりましたが(違うかもしれませんが……)、どういう流れで作成して行けばいいのか
さっぱりとわかりません。

C言語の知識は浅いですが、独学でBASICをかじっています。
(ギリギリポインタがわかりはじめた感じですが)

いきなりで不躾だとは思いますが、
プログラムの流れや詳しい考え方など、ご存じの方がいらっしゃいましたらご教授いただけませんでしょうか。
よろしくお願いいたします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 8年前
住所: 東海地方
連絡を取る:

Re: A*探索アルゴリズム

#2

投稿記事 by softya(ソフト屋) » 6年前

イメージ的なモノは、これが分りやすいかも知れません。
「経路探索アルゴリズムの「ダイクストラ法」と「A*」をビジュアライズしてみた - てっく煮ブログ」
http://d.hatena.ne.jp/nitoyon/20100126/ ... _visualize

ここが参考に成るでしょう。A*のベースとなったダイクストラ法です。
「グラフ構造を用いた経路探索(ダイクストラ法)」
http://tokyo-ct.net/usr/kosaka/for_stud ... ugi26.html
あとC#のサンプルコードです。
「A*(エースター:最短経路探索アルゴリズム)サンプル」
http://tkina.web.fc2.com/kaihatu/siryou ... Sample.htm
「ゲーム制作の舞台裏 エースターで最短経路探索」
http://tkina.blog60.fc2.com/blog-entry-326.html

コードではないですが
「A*」
http://www5f.biglobe.ne.jp/~kenmo/progr ... astar.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Nな人

Re: A*探索アルゴリズム

#3

投稿記事 by Nな人 » 6年前

softya(ソフト屋) 様

ご返信ありがとうございました。
完成はしませんでしたが、とても参考になりました!!
もっとゆっくり時間をかけて完成させて行こうと思います。

アバター
GRAM
記事: 164
登録日時: 8年前
住所: 大阪

Re: A*探索アルゴリズム

#4

投稿記事 by GRAM » 6年前

A*アルゴリズムとはダイクストラ法と呼ばれる探索アルゴリズムの改良なので
まずはダイクストラ法を理解することが大切です。
(というかダイクストラさえ分かればA*に変えるのは簡単です)

ダイクストラ法に関する説明は上記サイト(特に2番目)にある通りですので、
プログラムにするときに自分が考えることを挙げておきます。

まず、ダイクストラ法ですが僕が思うに次の3つの機構からなります。
どの言語を使うにしろ、この3つの機構が作れればできたも同然です。

①そこに行きつくまで合計コストが最小となる次の探索ノードを取り出す機構(プライオリティーキュー)
②取り出したノードがゴールかどうか判定し、またそこから伸びる各ノードへのコストを計算する機構
③最小コストの確定したノードを保存する機構(最短経路ツリー)

今各ノードは探索用に以下の3つの情報を持っているとしましょう。
①そのノードまでのコスト
②そのノードにたどり着く一つ前のノード
③そのノードから伸びる各ノードと自分のノードから各ノードに行くまでにかかるコスト


まず初めにプライオリティーキューにスタートとなるノードを加えます。
(ループはじめ)
①プライオリティーキューから一番コストの低いノードを取り出します。
  プライオリティーキューから取り出されるノードは、プライオリティーキューの性質上
  コストが確定されているノードです。(つまりコストが最も低い)
②そこで取り出したノード(ノードAとする)を最短経路ツリーに加えます。この時始めのノードの場合のみ一つ前のノードは記録されていません。
③ノードAがゴールならループを抜けます
④ノードAから伸びるノード(ノードBとする)へノードAからかかるコストを取得します。最短経路ツリーにノードBが入っていれば何もしません。
  そうでなければ、ノードAのコストと和をとってノードBのコストを算出します。
  プライオリティーキューにノードBが入っていなければ、ノードBのひとつ前のノードをノードAに設定しプライオリティーキューに加えます。
  プライオリティーキューにノードBがすでに入っていて、かつ今算出したコストのほうが低ければ、ノードBのコストを更新して、
  ノードBのひとつ前のノードを、ノードAに設定し記録します。実装によってはプライオリティーキューを更新します。
⑤④をノードAから伸びるすべてのノードについて行います
⑥(ループはじめ)に戻ります。

これで終わりです。
最短経路ツリーにはゴールまでの最短経路が記載されます。
というのも各ノードのひとつ前のノードが何かわかっているので、ゴールから順に初めのノードに向かってめぐっていけば、
勝手に最短経路が出来上がります。
実装が一番難しいのはプライオリティーキューですが、効率を考えなければそこまでではありません。
頑張ってください!

閉鎖

“C言語何でも質問掲示板” へ戻る