距離に関係しないコストを最小限に抑えながら、数直線上のポイントを訪れる


18

このACM ICPCの問題について、助けが必要です。私の現在の考えは、これを最短経路問題としてモデル化することであり、これは問題ステートメントの下で説明されています。

問題

あるN = 1000において1-Dの数直線に沿って位置する核廃棄物容器の別個の位置は-500,000 to 500,000、を除いx=0。人は、すべてのごみ箱を集める仕事をします。廃棄物容器が収集されない秒ごとに、1単位の放射線を放出します。人は1秒ごとにユニットx = 0を移動でき1、ごみの収集にかかる時間はごくわずかです。すべてのコンテナを収集している間に放出される放射線の最小量を見つけたい。

サンプル入力:

4にあるコンテナ[-12, -2, 3, 7]

これらのコンテナを収集するのに最適な順序は[-2, 3, 7, -12]50ユニットの最小排出量です。説明:人は-22秒後に行き、その時間の間2 unitsに放射線が放出されます。その後、彼は3(距離:)に移動し5、バレルが2 + 5 = 7放射単位を放出した。彼はその銃身がユニットを放出4したx = 7場所に到達するまでにさらに数秒かかります2 + 5 + 4 = 11。彼はそのバレルがユニットを放出19したx = -12場所に到達するのに数秒かかります2 + 5 + 4 + 19 = 302 + 7 + 11 + 30 = 50、これが答えです。

ノート

明らかなO(N!)解決策があります。ただし、最も近いものに移動する、または最も近いクラスターに移動するなどの貪欲な方法を検討しましたが、機能しませんでした。

私はこの問題についてかなり長い間考えてきましたが、それをグラフ検索問題としてモデル化しました。

  1. 0ベースライン位置として挿入します(これが初期状態になります)
  2. 次に、ポジションを最小から最大の順に並べ替えます。
  3. 私たちは、その後、BFS / PFS、やるstateから構成を
    • 二つの整数lr我々はすでに訪問していることをソートされた位置の配列の連続した範囲を表します
    • loc範囲の左端か右端のどちらにいるかを示す整数
    • time経過時間を示す整数
    • これまでの総コストを示す整数の「コスト」(訪問したノードに基づいて)
  4. 各状態から[l-1、r]および[l、r + 1]に移動し、他の3つの整数を適宜調整します。
  5. 最終状態は[0、N]で、両方の終了位置をチェックします。

ただし、[L, R, loc]状態を一意に定義するわけではないようで、これらをそれぞれL, R, loc, and time最小化costしながらを格納する必要があります。これは指数アルゴリズムにつながりますが、それでもまだ良い方法には遅すぎます。

誰かが私のアイデアを広げたり、正しい方向に押し進めたりするのを手伝ってくれますか?

編集:これは、おそらく動的プログラミング最適化問題としてモデル化できますか?考えてみると、グラフ検索ソリューションと同じ問題があります-電流costが低いからといって、それがそのサブ問題の最適な答えであることを意味するわけではありませんtime

貪欲は機能しません:特定の場所に移動するコストを推定する貪欲な選択アルゴリズムがあります(たとえば、右に移動すると、左のバレルまでの距離が2倍になります)。

ヒューリスティックを使用して、優先度優先の検索を実行できますか?ヒューリスティックは、現在の旅行のコストと経過時間を組み合わせることができます。


最短経路アルゴリズムはどうですか?ダイクストラのアルゴリズムが好きですか?
suraj_fale

私はそれを試しましたが、私は本当に間違ったことをしていると思います。番号付きのリストを使用して、アルゴリズム(優先順位優先検索またはBFS)を下部近くで説明しました。
バロンW.

これはあなたを助けるかもしれません... stackoverflow.com/q/14639346/585398
suraj_fale

申し訳ありませんが、これら2つの問題がどのように関連しているかはわかりません。説明できる?
バロンW.

2
これは、ACM ICPCの実践上の問題であり、実際の問題ではありません。別の注意として、私は州を削減しようとしたが、役に立たなかった。DPソリューションを作成しようとしましたが、それも機能しませんでした。状態はL、R、POSでした。
バロンW.

回答:


4

問題を位置のペアの有向グラフとして見ることで、これを改善できると思います。

この例では、値-9、-6、-1、3、5の行を使用します。

テキストだけでグラフを描くのは難しすぎるので、ペアを表として表現します。セルは、これらの2つの位置の間のすべてのコンテナが収集された状態を表すと考えることができます。各セルには2つの値があり、1つは左へ行くコストを表し、もう1つは右へ行くコスト(次のコンテナへ)を表します。

値は、2つのポイント間の距離にこれらの2つのポイントの外側の樽の数を掛けた値+ 1として単純に計算できます。両方の数字が同じ符号を持つセルは、反対の符号の樽がすべて収集された場合を表します。これらは、ゼロから離れる方向のバレル数のみを使用して計算されます。

表のXの値は、その方向に進むことができないことを意味します(その方向のすべての樽が取られています)。行はコレクターの現在の位置を表し、列は次の反対側のバレルの位置を表します。

    +------+------+------+------+------+
    |  -9  |  -6  |  -1  |   3  |   5  |
+---+------+------+------+------+------+
|-9 |      |      |      | X, 24| X, 14|
+---+------+------+------+------+------+
|-6 | 3, X |      |      | 9, 27| 6, 22|
+---+------+------+------+------+------+
|-1 |      |10, X |      |20, 8 |15, 18|
+---+------+------+------+------+------+
| 3 |24, 4 |27, 6 |16, 8 |      | X, 2 |
+---+------+------+------+------+------+
| 5 |14, X |22, X |18, X |      |      |
+---+------+------+------+------+------+

正方形間を移動するためのルールは、やや混乱する可能性があります。

負の番号の列の場合、ルールは次のとおりです。

  • 右に移動すると、1つのセルが下に移動します。
  • 左に移動すると、1つのセルが下に移動し、対角線を越えてミラーリングされます。
  • 右の値がXの場合、左に行くと対角線(列と行が等しい)に移動し、1つ左に移動します。

正の番号の列の場合、ルールは次のとおりです。

  • 左に移動すると、1つ上のセルに移動します。
  • 右に移動すると1つのセルが上に移動し、対角線を越えてミラーリングします。
  • 左の値がXの場合、右に進むと、斜め下に1つずつ右に移動します。

これで、ダイクストラのアルゴリズムを実行して、これらの移動ルールを使用してグラフをトラバースする最適なパスを計算できます。開始位置は(-1、3)と(3、-1)で、それぞれ初期コストは5と15です。2つの終了位置((-9、-9)の左と(5、5)の右)の値を計算したら、2つのうち小さい方が答えです。

各ステップの実行時間は次のとおりです。

  • O(N log N)は、入力値を最初に線に沿って並べ替えます
  • テーブル/グラフを計算するためのO(N ^ 2)
  • グラフ上でダイクストラを実行するためのO(N ^ 2 log N)(注:頂点には最大で2つのエッジがあります)。

最初の2つのステップは最後のステップに支配されているため、全体的なランタイムはO(N ^ 2 log N)であり、チャレンジに十分なランタイムです。


1

最短距離

昨日、問題を解決するためにJavaアプリケーションを作成しました。SRJがコメントで述べたように、この問題は基本的に最短距離の問題です。放射は、最短距離とともに値を累積できることを示しています。

基本的には、私がやったことです。

  • コンテナ番号をList <Integer>に入れます
  • リストには要素が含まれていますが;
    • 最も近い要素を見つける
    • 要素が1つある場合は、そこを歩いて要素を削除します。
    • 要素が2つある場合は、パスをコピーして両方の要素に移動します
  • 放射値が最小のパスを見つけます。

ここにアプリケーションからの出力があります

10 containers are located at [-90, -75, -47, -9, 9, 26, 48, 50, 64, 79].

You walk to position -9 and pick up the container.  The total radiation emitted is 90 units.
You walk to position 9 and pick up the container.  The total radiation emitted is 252 units.
You walk to position 26 and pick up the container.  The total radiation emitted is 388 units.
You walk to position 48 and pick up the container.  The total radiation emitted is 542 units.
You walk to position 50 and pick up the container.  The total radiation emitted is 554 units.
You walk to position 64 and pick up the container.  The total radiation emitted is 624 units.
You walk to position 79 and pick up the container.  The total radiation emitted is 684 units.
You walk to position -47 and pick up the container.  The total radiation emitted is 1,062 units.
You walk to position -75 and pick up the container.  The total radiation emitted is 1,118 units.
You walk to position -90 and pick up the container.  The total radiation emitted is 1,133 units.

私はアルゴリズムを決して最適化しませんでした。数字の入力リストがソートされていることにも気付きませんでした。(私はdoofusです。)

最大値、1,000コンテナー、-500,000〜500,000の範囲でコードを実行すると、コードの実行に3秒かかりました。その時間のほとんどは、コンソールに1,000印刷行を書き込むことでした。

私は大きなOの人ではありませんが、最短経路アルゴリズムを歩く総当たりはO(N!)ではなくO(N!)であると思います。

入力番号が並べ替えられているという事実を利用して、現在の場所の両側の2つの番号を確認するだけでよい場合、アプリケーションをO(N)に近づけることができます。リストにある要素を取得するときにリストから要素を削除するので、2つの番号をチェックするだけです。

貪欲なアルゴリズムなどのさまざまなアルゴリズムを使用して、近似解を見つけました。

私のプログラムの実行に3秒ではなく3時間かかっていた場合、選択する必要があります。

十分なソリューションで十分ですか?

言い換えれば、十分な答えを得るために処理速度を犠牲にするつもりはありますか?

十分な答えで十分であれば、近似アルゴリズムを使用します。

完璧な答えが必要な場合は、すべての最短経路を歩く必要があります。ショートカットはありません。

誰かが私のコードを投稿することを望んでいる場合、私はします。最短ウォークアルゴリズムを実装できるかどうかを確認したかったため、まだバグがあると確信しています。


1

私はこの問題を2^N時間内に解決する解決策を持っていますが、それは貧弱ですが、それは問題をフレーミングするのに役立つ方法だと思うので、投稿したいと思いました。

問題をグラフとしてモデル化するのではなく、バイナリ決定ツリー(たとえばT)としてモデル化します。各レベルで、右に行くか左に行くかを選択する必要があります。各エッジの「コスト」を計算するのはかなり簡単です。ましょうh(K)、現在のノードの高さK、に行くエッジのコストですleft_child(K) = h(K) x dist(K, left_child(K))。右の子のエッジのコストについても、同様の計算で十分です。このツリーを構築し、エッジの累積コストを最後まで追跡し、合計コストが最小のリーフノードへのパスを報告します。

各エッジの長さはdist(K, left_child(K))次のサイトに行く時間を表し、サブツリーの高さは残っているサイトの数(たとえば、まだ放射している)であるため、コスト計算が機能することに注意してください。

ここで、このフレームワーク内のトリックは、いくつかのブランチに沿った検索の展開を無視できることを「証明」するために使用できるヒューリスティックがあるかどうかを判断することです。私の直感では、そのようなヒューリスティックには、それを打ち負かすサイトの配置がありますが、誰かが何かを思いつく可能性があります。

多くの人がグラフに最短経路ソリューションを適用することを提案していますが、そのようなソリューションが機能するかどうかには疑問があります。問題の「グラフ」内の隣人は、あなたがたどる経路に応じて変わります。であなたのオリジナルのポストではたとえば[-12, -2, 3, 7]、あなたがに行く場合は-2、その後-123「隣人となり、あなたがに行く場合は3、その後-27隣接しています。正の値と負の値のすべての可能な「ペア」は、最終的なグラフで潜在的にneigbhoursになる可能性があります。動的グラフで証明できるほど正しい最短経路アルゴリズムは知りません。


0

すべてのステージを、最も近いバレルに右に行くことと、最も近いバレルに左に行くことの間のバイナリ選択として単に考えるのが最も理にかなっていると思います。何らかの動きをすることで合計で発生する放射線ユニットの数を詳述するコスト関数を用意し、最低コストのものを選択します。

単純に最も近いバレルを検討するのではなく、バレルから離れることで効果的に2倍の放射線を追加すると仮定します。

[-12、-2,3,7]の例では、左に移動すると、左側に合計14(2 + 2 + 10)、右側に18(2 + 2 + 5 + 9)が発生し、合計22。右に移動すると、右側に10(3 + 3 + 4)、右側に26(3 + 3 + 5 + 15)が発生します。明らかに、最初は正しいソリューションです。連続するすべての動きに対して同様の計算を行うことができます。

その後、問題は基本的に検索に帰着するため、複雑さはO(nlog(n))になります。これはO(n!)よりもはるかに優れています。これは基本的に比較ベースの検索アルゴリズムであり、O(nlog(n))よりもうまくやることができないため、これはこの問題に存在する可能性がある最も低い複雑さであると考えています

どうやら、この説明では十分に明確ではなかったので、もう少しプログラム的にすることにしました。最も安価な方向3.方向に移動するコストを計算する際の考慮から到達したバレルを削除します

コストの計算:1.指定された方向に最も近いバレルを特定します。$ distは、現在の位置から指定された方向の最も近いバレルまでの距離だとしましょう。2.コストはN * $ distとして初期化されます。Nはまだアクティブなバレルのみを考慮します。3.これに、$ distで示される新しい位置が残りのすべてのバレルからの距離を追加します。


1
これは常に機能するとは限りません。座標を並べ替えてから、状態に範囲[i..j](訪問した範囲を示す)とコストと現在の時刻が含まれる場所で検索を行うことができます。
バロンW.

これはいつ機能しないのですか?
スレータービクターオフ

これが失敗する簡単なテストケースがありました。私はそれを見つけるしようとするでしょうが、それはN = 4または5とした
バロンW.

[43, -18, -98, -82, 63]
バロンW.

のようなケースも[-10,-11, 10,20,30,40,50,60,70]。正しい唯一の解決策は、すべてのネガティブなものを収集してから、ポジティブなものを収集することです。455の答えのために
バロンW.

0

部分的な解決策-後で説明します。

「デフォルト」戦略は、左または右のどちらか安い方で実行されます。さて、もう1つの樽を手に入れるもう1つの方法として、ちょっとしたサイドトリップの価値があるかどうかを尋ねてください。答えを計算するのはかなり簡単です。

入力をサンプリングする場合、最後まで実行する方が、最後まで実行するよりも安価です。-2に行く価値はありますか?正しく実行してから0に戻すコストを14ずつ削減します(デフォルト戦略では、1移動につき4放射線ユニットを0から3に「支払った」ため、3から3になりました。 7、現在は2など)に加えて、1移動ごとに1つずつ減少し、0から-2に移動するコストが削減されます。

ただし、(16-14)= 2の正味ゲインに対して、-2に移動してから14の0に戻るコスト(移動ごとに4単位、-2に移動して3、0に戻る)が追加されます。これを計算するために、各決定ごとに問題全体を解決するための正確なコストを評価する必要がないことに注意してください-左端まで走るのが右端まで走るよりも安いかどうかを知るだけで十分な情報が得られます多くの廃棄物コンテナがあなたの両側にあり、最も近い2までの距離です。それがO(N ^ 2)です。

1つの重要な問題を除いて、最後まで最後まで実行すると想定しました。それをきれいにするには、計算を更新する必要があります。サンプル入力については、0から7までの実行中に1秒間に1単位の合計放射量を1減らすことで14を節約すると仮定しました。ただし、実行する前に7倍になると、節約量は減ります。

それはかなり悪いです。なぜなら、すべての可能性を試さずに次のダブルバックを計算する方法がわからないので、O(2 ^ N)に戻るからです。

例外-枝刈りでは2 ^ Nです。-2への「サイドトリップ」のコストは14であると計算しましたが、右端の番号に到達する前にサイドトリップがなかった場合は16になりました。右端の数字が5だった場合、-2へのサイドトリップが報われなかったことがすぐにわかります。(コストはまだ14、最大の利益は12)。また、-2に進んでから6に達する前にサイドトリップを行うことを検討する必要もありません。


0

パスが複雑である限り、文字列が(boolean、int、int、int、string)の2 * N ^ 2タプル以下を維持する幅優先検索を使用して解決できると思います。

タプルは(最小または最大のブール値、移動した最小位置、移動した最大位置、放出された総放射線量、経路履歴)です。

アルゴリズムは次のようになっています。

  1. タプルのプールを単一のエントリに初期化します(min、0、0、0、 "")
  2. 放射が最小のプール内の要素を見つけます。最小値と最大値がすべてのバレルの最小値と最大値に対応する場合、パス履歴が最適なソリューションです。それ以外の場合は、プールから削除します。
  3. このタプルの2つの子孫を計算します。各子孫は、次の未処理のバレルを左または右に歩くことに対応します。
  4. 子孫をプールに挿入します。プールに、新しい子孫と同じブール値、最小値、および最大値を持つ要素が既に存在する場合、より高い放射カウントを持つ要素を破棄します。
  5. 後藤2。

支配的なタプルを見つけて削除すると、パフォーマンスが劇的に向上します。各タプルに「has bred」フラグを追加し、プールに育種されたタプルを残すことは価値があるかもしれません。

また、タプルの保管方法を決定し、それらを検索して、支配および繁殖する新しい要素を検索する際に、いくつかの重要な決定を行う必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.