【问题标题】:Cubic (flood) fill立方(泛洪)填充
【发布时间】:2013-06-03 18:15:08
【问题描述】:

我有一个 3D 数组。在这个数组中,我想找到可以组合成更大元素的元素。矩形不能相互重叠。我最好先找到最大的矩形,但先到先得也不会错,尤其是如果这样可以提高性能。

例如

1 0 0 0 1
0 0 0 0 0
0 0 0 0 1
1 1 0 0 1

将产生(因为 3x3 是可以找到的最大矩形;位置 1, 0 到 3, 2 - zerobased):

0 0 0
0 0 0
0 0 0

和(因为 1x2 是可以找到的下一个最大矩形;位置 0、1 到 0、2):

0
0

和(因为 2x1 是可以找到的下一个最大矩形;位置 2、3 到 3、3):

0 0

当然还有(左边是位置 4, 1;不是更大但仍需要使用)

0

作为更大的元素(我只需要知道零或一)。目的是减少体素网格的对撞机数量。

我不知道这种算法的名称,也许我可以找到自己如何做到这一点。

如果有人可以为此提供一些可行的信息,那就太好了!

【问题讨论】:

  • 您可能正在寻找“区域增长算法”。
  • 您能说得更具体一点吗?
  • 好的,我会尝试添加一些额外的信息。
  • 是的,我认为您需要提供更多信息,例如,在您的情况下,为什么它不会产生 2*4 '0'(第 1-2 行,第 0-3 列) ?
  • 我添加了额外的信息;如果不清楚,请告诉。

标签: algorithm


【解决方案1】:

对于 2D 情况,用于查找最大矩形的算法是“直方图下的最大矩形区域”。这是一个非常简单的 O(n) 算法,也讨论过 here

诀窍是可视化您的矩阵实际上可能被处理为长度为mn 直方图 - 在每一行,从上到下,您有一个高度为0 的列(在您的示例中将由数字 1 表示),或者当当前字符为 0 时,高度为 height[i-1][j] + 1 的列。因此,每一行都在O(m) 中处理,总复杂度变为O(n*m)。现在,由于您想要所有矩形,而不仅仅是最大的矩形,您只需调整算法以“消耗”您满意的任何矩形,也就是说,每当您发现一个流浪的1 中断您的矩形形成时,您可以只“使用”上面将被中断的矩形,并确保它下面的其他位置将在高度 0 或 1 处重新开始,有效地设置 height[i-1][jbegin~jend] = 0。 (其中jbeginjend 是在i-1 行结束的矩形的开始和结束,您刚刚选择“使用”,因为它在i 行被阻止)

对于 3D 情况,您必须了解直方图算法的工作原理,以便开发您的适应,但它基本上应该成为上述更复杂的版本,跟踪额外的坐标。这可能不是最容易实现的方法,但如果您需要,它会产生最佳性能。

【讨论】:

  • 我同意您可以将其可视化为每行 1 个直方图。所以有n 大小为m 的直方图。 (如果数组是n*m)但是,要在每一行生成直方图,您需要遍历以n*m 为界的直方图区域。所以算法至少是O(n*n*m)
  • @Billiska 不,这就是为什么你要保留一个矩阵height[n][m]。您一次处理一行,使用您已经从上一行获得的信息更新其高度。所以在第 3 行,你正在处理你的矩阵,就好像你的直方图的高度最多为 3,然后你转到第 4 行。如果你发现一个数字 1 阻塞了一个列,这意味着你的列现在有效地代表一个高度0,并且您知道有一个矩形在其上方结束(除非它的高度也为 0)。事实上,你也只需要 O(m) 内存,但一开始你不必担心。
  • 这实际上是解决二维空间中最大矩形问题的最常用和最好的算法,如果你不明白为什么它的复杂度是O(nm),那是我解释得不够清楚是我的错。然而,我还没有看到它被应用于 3D 案例,但话说回来,这是我第一次看到有人对问题的 3D 版本感兴趣,而 2D 相当普遍和众所周知。 (不是你想要 *all 矩形的具体变体)
  • 我现在明白你的意思了。谢谢你。只是当您自己的算法结果为O(n^3) 时,您会产生一种偏见,即其他算法不应该更快。无论如何,既然我看到你提到想要所有矩形的变化,我才意识到我并不真正理解 OP。暂时删除我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多