36

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

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

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

回答がある場合は、アルゴリズム自体ではなくアルゴリズムの名前を投稿していただきたいことに注意してください (もちろん、アルゴリズムも投稿するとさらに良いでしょう)。たとえば、それがダイクストラのアルゴリズムであるか、フロイドのアルゴリズムであるか、またはその他のものであるかどうか。

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


わかりました、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);
}
};
4

8 に答える 8

44

Lee のアルゴリズム: 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 = 列数です。これは、グリッドに実装する最も簡単なアルゴリズムであり、実際には非常に効率的でもあると思います。ヒープを使用して実装すると、ダイクストラが勝つ可能性がありますが、従来のダイクストラよりも高速である必要があります。

于 2010-02-22T15:12:06.737 に答える
6

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

于 2010-02-22T14:36:26.290 に答える
5

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

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

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

于 2010-02-22T14:41:50.317 に答える
2

動きが十分に制限されている場合 (たとえば、右、または上、または斜め上と右にのみ移動できる場合)、重複部分問題と部分最適部分構造の性質を利用して、動的計画法を使用できます。

于 2010-02-22T14:52:55.997 に答える
1

私が理解できないのは、A と B の間の最短経路が必要な場合でも、 C と D が B を指している場合、A から C および A から D を見る必要はないということです。最短パスは、ACB または ADB である可能性が非常に高くなります。接続されていないノードを捨てるだけです。私のプロジェクトの 1 つで、ポイント A と B を取得し、他のポイントが接続されているかどうかを確認し、接続されていないポイントをグラフ全体から削除しました。次に、ダイクストラのアルゴリズムを使用しました。

于 2010-02-22T14:53:40.253 に答える
0

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

グリッドをグラフ形式にエンコードしたら、よく知られたグラフ アルゴリズム (既に認識されているようです) の中から選択して、必要な結果の種類 (最短パスなど) を走査するだけです。

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

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

于 2010-02-22T15:18:16.713 に答える