この有名なdpの問題は多くの場所で見つかりましたが、解決方法がわかりません。
N種類の長方形の3Dボックスのセットが与えられます。ここで、i番目のボックスの高さはh(i)、幅はw(i)、深さはd(i)(すべての実数)できるだけ高いボックスのスタックを作成したいが、2Dベースの寸法がの場合にのみ別のボックスの上にボックスをスタックすることができます下のボックスはそれぞれ、上のボックスの2Dベースのボックスよりも厳密に大きくなっています。もちろん、ボックスを回転させて、任意の側面をベースとして機能させることもできます。同じタイプの複数のインスタンスを使用することもできます。ボックス。
この問題は私には手順を理解するには複雑すぎるようです。 3Dなので、高さ、幅、奥行きの3つのシーケンスが得られます。しかし、3次元を交換することが可能であるため、問題は私にとってより複雑になります。したがって、誰かがスワッピングがないときに問題を解決するための手順と、スワッピング時にそれを行う方法を説明してください。私はその問題にうんざりした。だから、誰かが解決策を簡単な方法で説明してください。
動的計画法を使用してこれを解決できると思います 最長増加部分列 アルゴリズム: http://www.algorithmist.com/index.php/Longest_Increasing_Subsequence
回転の計算は非常に簡単です。すべてのタワーについて、高さをベースの長さとして使用し、幅を高さとして使用するとどうなるか、自然な方法で使用するとどうなるかを確認する必要があります。例えば:
=============
= =
= =
= = L
= H =
= =
= =
=============
W
次のようになります(ええ、私はそれが本来あるべきように見えないことを知っています、ただ表記に従ってください):
==================
= =
= =
= W = L
= =
= =
==================
H
したがって、各ブロックには、実際には可能な回転を表す3つのブロックがあります。これに従ってブロック配列を調整してから、ベース領域を減らして並べ替え、DPLISアルゴリズムを適用して最大の高さを取得します。
適応された漸化式は次のとおりです。D[i] =最後の塔がiでなければならない場合に取得できる最大の高さ。
D[1] = h(1);
D[i] = h(i) + max(D[j] | j < i, we can put block i on top of block j)
Answer is the max element of D.
ここでこれを説明するビデオを参照してください: http://people.csail.mit.edu/bdean/6.046/dp/
スタックは、x、y、zトリプレットのシーケンス(x、yは2D平面、zは高さ)と見なすことができます。ここで、x(i)> x(i + 1 )およびy(i)> y(i + 1)。目標は、使用可能なトリプレットのセットからトリプレットを選択するzの合計を最大化することです。各トリプレットは1つのタイプのボックスです。特定の方向。制約x> yを適用しても、解空間が減少しないことは非常に簡単です。したがって、各ボックスは、w、h、dのそれぞれをz座標として持つ3つのトリプレットを生成します。
トリプレットを、x、y制約が満たされたときに、長さzのエッジが2つのトリプレットの間に存在する有向非巡回グラフと見なす場合、問題は、そのグラフを通る最長のパスを見つけることです。
まず、この問題を2次元で解決してみましょう。
xとYの長方形があり、質問が似ているとします(最も高い塔ですが、今回は1つの基本寸法のみを気にする必要があります)。
最初に、コレクション全体を調べ、正方形(X(1)= X(2)&& Y(1)=)を除いて、各長方形を90度回転(XとYを入れ替え)して複製します。 Y(2))。これは、考えられるすべてのバリエーションを表しています。
次に、X側で最大から最小の順に並べ替えます。 X値が重複している場合は、Y値が小さい方を削除します。
3Dシナリオに適用されるのと同じ原則ですが、コレクションのサイズに6(W、H、Dのすべての可能なバリアント)を掛けるのではなく、2を掛けるだけです。これは、幅が狭いすべてのバリエーションを閉じることによって行います。深さよりも(したがって、各iについて、W(i)> = D(i))、高さが3次元の最高でも最低でもないバリエーションを却下します(他の2つのバリエーションが1つになる可能性があるため)他の上にあり、これは参加できません)。ここでも、重複を却下します(ここで、W(1)= W(2)&& H(1)= H(2)&& D(1)= D(2))。
次に、幅で並べ替える必要がありますが、今回は同じ幅のバリエーションを破棄しないでください(タワーに収まる場合と収まらない場合があるため)。次に、上記のLISアルゴリズムを使用できます。 @IVlad:
D[1] = h(1);
D[i] = h(i) + max(D[j] | j <= i and we can put tower i on tower j) or simply h(i) if no such D[j] exists.
秘訣は、幅が2つの中で最も長いことを知っているので、最初の要素が後の要素の上に収まらないことを知っています。
この問題の解決策は、3つのステップで構成されています。
O(n^2)
アルゴリズム 。3番目のステップは最もコストがかかり、ソリューションの複雑さをO(n^2)
にぶつけます。アプローチの完全な説明、各ステップが答えを見つけるのにどのように貢献するか、および完全なコードを読みたい場合は、 問題について書いたブログ投稿 を参照してください。
ツリー(またはある種のツリー構造)を作成し、深度検索で解析して、個々の垂直方向の「高さ」(回転に依存)値から最大高さを計算することをお勧めします。
これ(これが基本的なアプローチだと思います)。
詳細の詳細:
木の根は、立方体が収まる床である必要があります。そこから、可能な次の(現在のボックスの上に特定の回転で配置できるボックス)ボックスの子ノードを作成するだけです。各ボックスに対して再帰的にそれを行いますおよび回転。
木が建てられたら、それを通り抜けて、床から木の葉までの塔の高さの合計を計算します。