web-dev-qa-db-ja.com

2Dグリッド上の(0,0)から(N、N)への最小コストパス

(0、0)から(N、N)までの最短パスを見つけようとしている2Dグリッドに問題があります(1 <N <10 ^ 9)。 P(1 <P <10 ^ 5)のショートカットもあり、(x1、y1)から(x2、y2)にジャンプできます。

旅行するときは、上または右にしか歩くことができません。同様に、ショートカットによって下または左に移動することはありません。

サンプルケース:(0、0)にいて、(3、3)に到達しようとしています。 2つのショートカットがあります。1つは(0、1)から(0、2)に移動し、もう1つは(1、2)から(2、3)に移動します。

最良の道は:

(0,0)から(0,1)(1単位)に移動します。 (0,2)へのショートカット。 (0,2)から(1,2)(1単位)に移動します。 (2,3)へのショートカット。 (2,3)から(3,3)(1ユニット)に移動します。

したがって、全長は3ユニットになります。

時間枠も2秒です。

編集1:動的プログラミングを使用して、コストマトリックスを作成するというアイデアがありました。 matrix [i] [j] =到達するパスの総コスト(i、j)。ただし、グリッドは巨大で、マトリックスには10 ^ 18スロットがあり、これは大きすぎて時間枠に収まりません。

編集2:私が持っていた次のアイデアは、ダイクストラのアルゴリズムを使用することでした。グラフのすべてのノードを終了、開始、およびショートカットにするだけです。ただし、これはO(N ^ 2)ソリューションになります(エッジは最大で10 ^ 10です!)

編集3:別のO(N ^ 2)ソリューションを思いつきました。基本的に、すべてのショートカットは、それらのOriginからの距離に基づいてソートします。次に、すでに処理したすべてのショートカットを反復処理することにより、各ショートカットへの最短パスを見つけます。 (distTo(各ショートカット)+ manhattan_distance(each_shortcut、現在のショートカット))の最小値がわかります。最後に、(N、N)ポイントを、最終的な解決策を見つけるためのショートカットであるかのように処理します。

しかし、これはまだ遅すぎます-私のソリューションをさらに最適化する方法はありますか?

6
cracra

あなたは絶対的に最高の解決策を見つける必要がありますか、それとも非常に良い解決策を見つける必要がありますか?現実世界のほとんどのCSの問題では、非常に良い解決策をすばやく見つけることは、絶対的に最善の解決策をゆっくりと見つけることよりも優れています。

非常に優れたソリューションがすぐに望ましいと仮定すると、これは私のアプローチです:

ショートカットを、どれだけ優れているか(つまり、マンハッタンの距離が節約できる距離)に基づいて並べ替えます。

上位Mのショートカットの場合、Mは利用可能なショートカットのごく一部(1/100、おそらく1/1000)ですが、そのショートカットを使用する「非常に良い」パスを計算します。次に、それらのパスの最良のものを選択します。

テストしている各ショートカットについて、再帰を使用して、開始から入口までで定義された長方形の「非常に良い」パスと、出口から最後までで定義された長方形のパスを見つけます。既にショートカットを並べ替えているので、小さな長方形内にある上位M個のショートカットを見つけています。あなたがそれらを通過するときにそれらを数えるので、あなたは再び、それらの一番上の小さな部分を使用しています。

保存した各ショートカットの構造内で、ショートカットを取得すると、そのショートカットの始点までの距離と、終点から完全なマトリックスの終点までの距離。これにより、かなりの剪定が可能になります。

再帰を完了して最適なパスを選択したら、そのパスが何であるかを言えるように再帰を繰り返す必要がありますが、すべてのステップが事前に切り詰められるため、実際には非常に細い「ツリー」になります(引用符で囲まれているため、分岐しません)。

0
Zag