6

私はこのTopCoderの問題について何時間も考えようとしてきましたが、完全に機能する解決策を見つけることができず、めちゃくちゃ美しく使用されている以下の解決策を見つけました!

このソリューションが特定のプローブに対してどのように機能するかを理解しようとしていますか?そして、私は最初にそれをどのように考えることができましたか?解決策を読んだ後、私はそれがハフマンコーディングの変形であると思いましたが、それは私が得ることができる限りです。私は本当に夢中になっていて、どのような考え方がこの解決策につながるのか知りたいです。

問題は次のとおりです: http ://community.topcoder.com/stat?c = problem_statement&pm = 11860&rd = 15091

FoxCielにはやるべき宿題がたくさんあります。宿題は、いくつかの相互に独立したタスクで構成されています。タスクが異なれば、完了するまでに時間がかかる場合があります。int[]workCostが与えられます。iごとに、i番目のタスクが完了するまでにworkCost[i]秒かかります。彼女はパーティーに参加して友達に会いたいので、すべてのタスクをできるだけ早く終えたいと思っています。

主な問題は、シエルを含むすべてのキツネが宿題をするのを本当に嫌うということです。各キツネは、タスクの1つだけを喜んで実行します。幸いなことに、22世紀のロボット猫であるドラえもんは、フォックスシエルにスプリットハンマーを与えました。これは、任意のキツネを2つのキツネに分割できる魔法のガジェットです。

intsplitCostが与えられます。キツネにスプリットハンマーを使用するのは瞬時です。キツネにハンマーを使うと、キツネは裂け始めます。splitCost秒後、彼女は2つのキツネに変わります-元のキツネともう1つの完全に新しいキツネです。キツネが分裂している間、キツネにハンマーを再び使用することは許可されていません。

タスクの作業を中断することはできません。キツネがタスクの作業を開始したら、それを終了する必要があります。複数のキツネが同じタスクで協力することは許可されていません。キツネはハンマーを使って分割されている間はタスクに取り組むことができません。同じキツネを複数回分割することが可能です。彼女がタスクの1つを解決する前と後の両方でキツネを分割することが可能です。

キツネがすべてのタスクを解決できる最小時間を計算して返します。

そして、これが私がこのリンクで見つけた解決策です

import java.util.*; 

public class FoxAndDoraemon { 
  public int minTime(int[] workCost, int splitCost) { 
    PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); 

    for(int i : workCost) pq.offer(i); 

    while(pq.size()>=2) { 
      int i = pq.poll(); 
      int j = pq.poll(); 
      pq.offer(Math.max(i, j) + splitCost); 
    } 
    return pq.poll(); 

  } 
}
4

2 に答える 2

6

まず最初に、 `max(i、j)+splitCost'の背後にある理由を理解します。そうでしょう?基本的に、キツネが1匹いる場合は、キツネを2匹に分けて、各タスクを個別に実行します。このプロセスを「マージ」と呼びましょう。

ここで、a> b> cとなるような3つのジョブa、b、cがあると仮定します。merge(merge(a、b)、c)またはmerge(merge(a、c)、b)またはmerge(merge(b、c)、a)のいずれかを実行できます。計算を行うと、merge(merge(b、c)、a)がこれら3つの中で最も少ないことを証明できます。

これで、誘導を使用して、このソリューションが任意の数のジョブ(3つだけではない)に有効であることを証明できます。

于 2012-04-27T18:47:22.713 に答える
3

それは一から木を建てています。

アルゴリズムは、1つの基本的な事実を使用して機能します。つまり、2つの最小要素を削除すると、最小要素の計算コストは​​、次に小さい要素に分割を加えたコストよりも常に低くなります。(これについてのより完全な証拠については、ElKaminaの投稿を参照してください)。

したがって、ツリーに2つの要素(たとえば4と2)しかなく、分割コストが4の場合、最小時間は常に8(最小の要素の次に分割のコストを加えたもの)になります。

したがって、ツリーを構築するには、workCost [1,3,4,5,7,8,9,10]を取得し、splitCostが3であるとします。

そこで、2つの最小要素である1,3を見ていきます。これらを計算するための「コスト」は、最小で6です(最大数に分割のコストを加えたものです。次に6をキューに再挿入することにより、基本的にサブツリーを追加します。

  6
1   3

ここで、「高さ」/「コスト」は合計6です。このプロセスを繰り返すことにより、可能な限り最小のサブ要素(既存のサブツリーまたは新しい未完成の宿題)を使用してツリーを構築します。

解決策は最終的に次のようになります:(ここで、S(X)は分割とその下のすべての解決のコストです)

                  S(17)
            S(13)       S(14)
       S(10)     9   10      S(11)
  S(6)      7            S(8)     8
1     3                 4    5

このツリーを逆方向にトレースすると、式がどのように解決したかを簡単に確認できます。1と3のコストはS(6)、4と5はS(8)、S(6)と7はS(10)です。 )、8およびS(8)はS(11)などです。

于 2012-04-27T19:11:12.393 に答える