没有重复的盒子堆叠
Posted
技术标签:
【中文标题】没有重复的盒子堆叠【英文标题】:Box stacking without repetitions 【发布时间】:2013-02-24 10:19:30 【问题描述】:给定一组 n 种类型的矩形 3-D 框,其中第 i^th 框的高度为 h(i),宽度为 w(i),深度为 d(i)(均为实数)。您想创建一个尽可能高的盒子堆叠,但如果下层盒子的 2-D 底座的尺寸每个都严格大于 2-D 盒子的尺寸,您只能将一个盒子堆叠在另一个盒子的顶部。上盒的 D 底座。当然,你可以旋转一个盒子,让任何一面作为它的基础。你不能在一个盒子上使用多个实例。
这个问题已在 SO (Box stacking problem) 上提出,但没有“没有重复”的限制。 我们如何使用 LIS 解决这个问题。
我设计了以下解决方案,可以讨论一下
H[j] = max(H[j],max(H[i]|i<j, D[j] < D[i] , W[j]<W[i]+ H[j] -H[j'] )
其中 h[j'] 什么都不是,但如果第 j 个盒子已经习惯了 计算 H[i] 。由于允许旋转,因此 H[j] 可以是宽度或 第j个框的深度
【问题讨论】:
除了 LIS 的经典尺寸外,您可能还需要另一个尺寸来指定框的方向。 是的,已存储,否则 h[j'] 将不可用 那你的问题是什么?我认为除了公式之外,最好用文字解释您的工作,因为我们更容易遵循您的想法。 我想要一个解决方案,最好是 LIS。我已经在 LIS 中实现了,看起来它在所有情况下都不起作用。虽然它通过了我所有的测试用例。很快就会发布我的代码 这里是代码。不要在问题陈述中添加代码,因为它可能会淡化讨论。 gist.github.com/devshop/d9df1479a04af560b19b 【参考方案1】:您可以使用the link you provided 中的 DP 解决方案,并通过在每个位置设置大小为 n 的位图来摆脱“不重复”的限制。
这听起来确实像您计划的解决方案,但我并没有完全遵循您的公式或代码。
每个框的索引在它的 3 次旋转之间是公共的,并且设置了位图中用于框索引的位以确保不会处理同一框的下一次旋转。
for i = 1:n
Box b = inputi
(h3i , w3i , d3i ) = getRotation1(b)
(h3i+1, w3i+1, d3i+1) = getRotation2(b)
(h3i+2, w3i+2, d3i+2) = getRotation3(b)
index3i = index3i+1 = index3i+2 = i
// sort the 4 fields simultaneously (hi, wi, di, indexi all belong to the same box)
// (easy to do in OOP by storing these 4 in the same object)
sortByAreaDesc(h, w, d, index)
H[0] = 0
bitmap0 = false
for j = 1:3n
H[j] = maxi < j, wi > wj, di > dj if (bitmapj[ indexi ]) 0 else H[i] + hj
bitmapj = bitmapi from max
bitmapj[ indexi from max ] = true
return maxj H[j]
需要 O(n2) 时间和空间。
【讨论】:
您确定要开始 i=1:3n 的循环吗?不应该是j吗?既然一个盒子有3种组合,而且数组是按面积排序的,那么在计算h[j]的时候,我们如何保证h[j]所属的盒子还没有被设置在h[i]中呢?跨度> @NandishA 是的,只是我这边的打字错误。编辑希望能让它的工作原理更清晰。 不,我不认为这会解决问题,它会得到不重复的结果,但我们得到的高度不会是最好的! @NandishA 请发布一个它不起作用的测试用例。 它不适用于某些先前的堆栈被忽略的情况,因为它们包含当前框,但如果其中的当前类型的框被旋转,它们会给出更高的结果。考虑 2D 情况,2 个盒子(base, height):(4,1), (3,2),当试图添加盒子 (1, 4) 的最后一个方向时,你不能,因为你已经获得了次优解 (4,1)-(2,3)。【参考方案2】:此结果最初是针对 2D 情况得出的,但仍适用于 3D 框,如最后所述。
如果最佳塔中的所有盒子都或可以与其长尺寸 E-W 对齐,那将很方便。
假设一组具有最佳塔的盒子需要一些(非零)数量的盒子同时面向 E-W 和 N-S。旋转这样的塔,使最底部的盒子与 E-W 对齐。现在考虑最低的框 i,它是 N-S 对齐的。显然盒子 i 的长尺寸小于它的支持盒子 i-1 的最小尺寸;所以盒子 i 的长尺寸小于盒子 i-1 的长尺寸。
同样,由于框 i 的短维度小于框 i 的长维度,通过传递性我们知道框 i 的短维度小于框 i-1 的短维度。因此,从盒子 i 向上的整个子塔可以旋转 90 度以对齐盒子 i E-W。
随着我们登上塔楼重复,很明显,所有盒子都可以在任何最佳塔楼中以 E-W 对齐。
因此,每个盒子在最佳塔中只有这些可能的“方向”:
面向高度:最长垂直尺寸,第二长的东西方向; 面向长度:最长尺寸 E-W,第二长尺寸垂直; 面向宽度:最长尺寸 E-W,第二长尺寸面向 N-S; 缺席。【讨论】:
我说的是使用哪个面作为基础(有 3 种选择),所以我会添加一个维度来指示使用框的哪个面。我不确定你的答案是如何相关的。 @nhahtdh:哎呀!我正在解决一个更简单的案例。泰。以上是关于没有重复的盒子堆叠的主要内容,如果未能解决你的问题,请参考以下文章
Swift:如何确保没有无限的ViewController堆叠在一起(如果需要,如何解除它们)? [重复]