盒子堆叠问题

时间:2010-02-24 21:02:41

标签: algorithm dynamic-programming

我在许多地方发现了这个着名的dp问题,但我无法弄清楚如何解决。

  

您将获得一组n种类型的   矩形3-D盒子,其中第i个   盒子有高度h(i),宽度w(i)和   深度d(i)(所有实数)。您   想要创建一堆盒子   尽可能高,但你可以   只在另一个盒子的顶部堆叠一个盒子   如果二维基础的尺寸   下面的盒子每个都严格更大   比那些二维基地的那些   更高的盒子。当然,你可以旋转   一个盒子,任何一方的功能   它的基础。它也是允许使用的   多个相同类型的实例   框。

这个问题对我来说似乎太复杂了。因为它是3D,我得到三个高度,宽度和深度序列。但是因为有可能交换3维,问题对我来说变得更加复杂。所以请有人解释在没有交换时解决问题的步骤,然后在交换时如何解决问题。我对这个问题感到厌倦。所以,请有人解释解决方案。

5 个答案:

答案 0 :(得分:26)

我认为你可以使用动态编程最长增长子序列算法来解决这个问题:http://www.algorithmist.com/index.php/Longest_Increasing_Subsequence

旋转的计算很容易:对于每个塔,你需要检查的是如果你使用它的高度作为基座的长度和它的宽度作为高度会发生什么,如果你以自然的方式使用它会发生什么。例如:

=============
=           =
=           =
=           = L
=     H     =
=           =
=           =
=============   
      W

变成类似的东西(是的,我知道它看起来没什么应该的,只需按照符号):

==================
=                =
=                =  
=       W        = L
=                =
=                =
==================
        H

因此,对于每个块,您实际上有3个块表示其可能的旋转。根据此调整块数组,然后通过减小基本区域进行排序,并将DP LIS算法应用于获取最大高度。

适应性重现是: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/

答案 1 :(得分:5)

可以将堆栈视为x,y,z三元组的序列(x,y是2D平面,z是高度),其中x(i)> x(i + 1)和y(i)> Y(I + 1)。目标是最大化从可用三元组集合中选择三元组的总和 - 每个三元组是特定方向的一种类型的盒子。很容易看出强制执行约束x&gt; y不会减少解决方案空间。因此每个盒子生成3个三元组,每个w,h,d作为z坐标。

如果你认为三元组是有向非循环图,其中当两个三元组之间的x,y约束满足时,长度为z的边存在于两个三元组之间,则问题在于找到通过该图的最长路径。

答案 2 :(得分:3)

让我们首先尝试在二维中解决这个问题:

说你有X和Y的矩形,问题类似(最高塔,但这次你只需要担心一个基本尺寸)。
所以首先,你遍历整个集合,通过旋转90度(交换X和Y)复制每个矩形,除了正方形(其中X(1)= X(2)&amp;&amp; Y(1)= Y( 2))。这代表了所有可能的变化 然后你按它们的X面排序,从最大到最小。如果是重复的X值,则删除Y值较低的那个。

在3-D场景中应用相同的原则,只是现在你不要将集合的大小乘以6(W,H,D的每个可能的变体),而是乘以2.你通过忽略所有变化来实现这一点。宽度低于深度(因此对于每个i,W(i)> = D(i)),然后忽略高度不是三维的最高值或最低值的变化(因为其他两个变化)可以一个在另一个之上,这个不能加入)。再次,你也解除重复(其中W(1)= W(2)&amp;&amp; H(1)= H(2)&amp;&amp; D(1)= D(2))。
然后你应该按宽度排序,只有这一次你不要;扔掉相同宽度的变化(因为一个可能适合另一个可能没有的塔)然后你可以使用如上所述的@IVlad的LIS算法:

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.

诀窍是,你知道宽度是两者中最长的,所以你知道第一个元素不适合任何后面的元素。

答案 3 :(得分:0)

我建议您创建一个树(或某种树结构)并使用深度搜索对其进行解析,从单个垂直“高度”(取决于旋转)值计算最大高度。

这(我认为这是基本方法)。

详细信息:

树根应该是地板,任何立方体都适合。从那里你只需创建下一个可能的子节点(可以放置在当前框顶部的某个旋转的框)框。 递归地为每个框旋转。

构建树时,仔细检查并将总塔高度从 floor 计算到树的叶子。

答案 4 :(得分:0)

问题的解决方案包括三个步骤。

  1. 为每个方框排序尺寸,以便比较任意两个方框,以减少它们对应的相应尺寸。
  2. 按字典顺序对框的顺序排序,以便对于每个框,左侧的框是可能适合的框。
  3. 申请the O(n^2) algorithm for the Longest Increasing Subsequence Problem
  4. 第三步是最昂贵的,并将解决方案的复杂性提升到O(n^2)。 如果您想阅读该方法的完整说明,每个步骤如何帮助您找到答案,以及完整的代码,请查看the blog post I wrote about the problem