web-dev-qa-db-ja.com

グリッド内の2点間の最短経路を計算する方法

幅優先、全ペア(フロイド)、ダイクストラのように、グラフまたはグリッド内の2点間の最短パスを計算するために、多くのアルゴリズムが利用可能であることを知っています。

ただし、気づいたように、これらのアルゴリズムはすべて、関心のある2つのポイント間のパスだけでなく、そのグラフまたはグリッド内のすべてのパスを計算します。

私の質問は:グリッド、つまり2次元配列があり、2点間の最短経路の計算に興味がある場合、たとえばP1 P2、およびグリッド上での移動方法に制限がある場合(たとえば、斜め方向のみ、または斜め上方向のみなど)、どのアルゴリズムがこれを計算できますか?

答えがある場合は、アルゴリズム自体ではなく、アルゴリズムの名前を投稿してください(もちろん、アルゴリズムも投稿する方が良いでしょう)、たとえば、 Dijkstraのアルゴリズム、またはFloydのアルゴリズムなど

私を助けてください、私はこれについて何ヶ月も考えてきました!


よろしくお願いします。このアルゴリズムは、TOPCODER.COMでグリッド内で(斜め上に)しか移動できませんが、どのアルゴリズムを知っているかわかりません。

#include<iostream>
#include <cmath>

using namespace std;




inline int Calc(int x,int y)

{



if(abs(x)>=abs(y)) return abs(x);
int z=(abs(x)+abs(y))/2;
return z+abs(abs(x)-z);
 }

class SliverDistance
{


    public:
int minSteps(int x1,int y1, int x2, int y2)
{
    int ret=0;
    if(((x1+y1)&1)!=((x2+y2)&1))y1++,ret++;
    return ret+Calc(x2-x1,y2-y1);
}
};
33
Alan_AI

リーのアルゴリズム: http://en.wikipedia.org/wiki/Lee_algorithm

それは本質的にBF検索です、ここに例があります: http://www.oop.rwth-aachen.de/documents/oop-2007/sss-oop-2007.pdf

それを効果的に実装するには、ここで私の答えを確認してください: FloodFill-Algorithmを変更して、2つのデータポイントのボロノイ地域を取得しますか? -マークと言うとき、マークあなたが+1から来た位置の数で。

たとえば、このグリッドがある場合、* =障害物であり、上下左右に移動でき、Sから開始してDに移動する必要があり、0 =自由位置にある場合:

S 0 0 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

Sをキューに入れてから、「展開」します。

S 1 0 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

次に、そのすべての近隣を展開します。

S 1 2 0
* * 0 *
* 0 0 *
0 0 * *
* 0 0 D

そして、それらすべての隣人の隣人:

S 1 2 3
* * 3 *
* 0 0 *
0 0 * *
* 0 0 D

など、最終的には次のようになります:

S 1 2 3
* * 3 *
* 5 4 *
7 6 * *
* 7 8 9

したがって、SからDまでの距離は9です。実行時間はO(NM)です。ここで、N =行数、M =列数です。これはグリッドに実装するのが最も簡単なアルゴリズムであり、実際には非常に効率的だと思います。ヒープを使用して実装すると、ダイクストラが勝つ可能性がありますが、従来のダイクストラよりも高速になります。

40
IVlad

A Star(A *) アルゴリズムを使用します。

6
newdayrising

あなたは知らされないかもしれません。ダイクストラのアルゴリズムにはさまざまなバリエーションがあります。各ポイントから他のすべてのポイント(フロイドのような)までの最短経路を計算します。

ただし、一般的なダイクストラアルゴリズムは優先度キューに基づいており、必要な最短パスのみを計算します。実行中にいくつかのパスを構築しますが、それらはすべて、Aから最終的なソリューションパス上にある他のノードへの部分的なパスです。

したがって、グリッドをグラフとして簡単に解釈し(それに応じて対角線などの制限を考慮することができます)、その上でAからBへの最短パスのダイクストラ検索を実行できます。それは本当にあなたの問題をモデル化するだけの問題であり、あなたがいくつかの派手なアルゴリズムを必要とすることではありません。

5
Frank

動きが十分に制限されている場合(たとえば、右、上、または斜めの上下にしか移動できない場合)、重複するサブ問題とサブ最適なサブ構造の性質を活用して、 動的プログラミング

2

python BFSを使用した(0,0)から(0、m-1)への行列の最短パスの実装です。可変ポイントに合わせて変更できます。

n,m,k1,k2=[int(i) for i in input().split()]
arr=[[int(j) for j in input().split()] for i in range(n)]
x=[[-1 for i in range(m)] for j in range(n)]
x[0][0]=0
vis={}
q=[(0,0)]
while len(q)!=0:
    curr=q[0]
    rem=q.pop(0)
    vis[curr]=True
    r=curr[0]
    c=curr[1]
    if r-1>=0 and arr[r-1][c]==0:
        if vis.get((r-1,c),-1)==-1 or vis[(r-1,c)]!=True:
            q.append((r-1,c))
            x[r-1][c]=x[r][c]+1
    if r+1<n and arr[r+1][c]==0:
        if vis.get((r+1,c),-1)==-1 or vis[(r+1,c)]!=True:
            q.append((r+1,c))
            x[r+1][c]=x[r][c]+1
    if c-1>=0 and arr[r][c-1]==0:
        if vis.get((r,c-1),-1)==-1 or vis[(r,c-1)]!=True:
            q.append((r,c-1))
            x[r][c-1]=x[r][c]+1
    if c+1<m and arr[r][c+1]==0:
        if vis.get((r,c+1),-1)==-1 or vis[(r,c+1)]!=True:
            q.append((r,c+1))
            x[r][c+1]=x[r][c]+1
    #for i in x:
        #print(i)
ans=x[0][m-1]
if ans==-1:
    print(-1)
else:
    print(ans)
  • 入力行列は0と1で構成する必要があります。 0は移動の可能性を示します。
  • nは行数です。
  • mは列数です。
  • arrは与えられた行列です。
  • xは(0,0)からの距離行列です。
  • visは、ノードが訪問された場合にブール値を与える辞書です。
  • -1の出力は、そのようなパスが存在しないことを示しています。
1
Apurv

私が理解できないのは、AとBの間の最短経路が必要な場合、AからCおよびAからDを見る必要はありませんか?if CおよびDはBを指しますか?最短パスはA-C-BまたはA-D-Bになります。接続されていないノードを捨てるだけです。私のプロジェクトの1つで、ポイントAとBを取り、接続されている他のポイントを確認し、グラフ全体から削除されなかったポイントを確認しました。その後、ダイクストラのアルゴリズムを使用して進めました。

1
Dave

グリッドはグラフを形成します(または少なくともグラフとして表示できます)。いくつかの移動方向を排除することは、それが有向グラフであることを示します。あるノードから別のノードにまったく移動できない場合、それはグラフに存在しないエッジです。

グリッドをグラフ形式にエンコードしたら、よく知られているグラフアルゴリズムの中から選択して、目的の結果のタイプ(最短パスなど)でそれを走査するだけです。

編集:あなたが投稿した答えを見てきましたが、そのコードが何をすべきか/するべきかはわかりません。たとえば、if(y>=0) max(abs(x),y);があります。これは(少なくとも私には)あまり意味がないように思われます-maxからの結果は単に捨てられます。有用な何かを達成するには、それを返すか割り当てるか、その順序で何かをする必要があります。現状では、コンパイラがデッドコードとしてそれを見つけ、それに対して何も生成しないことを期待できます。

私の推測では、コードは実際には意図したとおりに機能せず、有用な何かをするのであれば、それは設計よりも偶然のものです。このような問題を解決して、それが何をしたのかを本当に確信できるようにするには、かなりの時間と労力が必要になります。

0
Jerry Coffin