我认为动态编程可能是你的朋友。
我看到的第一步是将多面体划分为一个简单的块集合,以便每个可能的面都可用(即,将其切成尽可能小的块)。这应该是微不足道的,因为一切都是轴对齐的盒子,所以类似 k-tree 的解决方案就足够了。
这似乎是合理的,因为我可以看看它的成本。这样做的代价是我“忘记”了 hyperslab 的原始配置,选择用一组新的 hyperslab 替换它。这可能使我误入歧途的唯一方法是原始配置是否可以为解决方案提供一些东西。鉴于您想要所有配置的“最佳”解决方案,我们必须假设原始结构不是很有帮助。我不知道是否可以证明这些原始信息是无用的,但我将在这个答案中做出这个假设。
该问题现在已简化为类似于约束生成森林问题的图问题。我认为查看问题最自然的方法是将其视为图形着色问题(只要您可以避免将其与更著名的图形着色问题混淆,即尝试在没有相同颜色共享的两种状态的情况下为地图着色边框)。我有一个节点图(小块),我希望为每个节点分配一种颜色(最终将是覆盖该块的“hyperslab”)。我有一个约束,我必须在 hyperslab 形状中分配颜色。
现在一个关键的观察是,不必考虑所有可能性。以我们想要看到的最终彩色图为例。我们可以通过将跨分区的任何超平板分成两部分来以任何我们喜欢的方式对该图进行分区。然而,并不是每个分区都是有意义的。唯一有意义的分区是轴对齐切割,它总是将一个超板分成两个超板(与如果切割不是轴对齐可能出现的任何更复杂的形状相反)。
现在这个削减与我们真正想要解决的问题相反。切割实际上是我们在第一步中所做的事情。虽然我们想找到最佳的合并算法,但要撤消这些削减。然而,这显示了我们将在动态编程中使用的一个关键特征:唯一重要的合并特征是在切割的暴露表面上。一旦我们找到形成中心区域的最佳方式,它通常不会在算法中发挥作用。
让我们从构建超平板空间的集合开始,它不仅可以定义普通超平板,还可以定义任何超平板配置,例如带有孔的超平板。每个超空间记录:
- 其中包含的叶 hyperslab 的数量(这是我们最终要尽量减少的数量)
- hyperslabs 的内部配置。
- 超平板空间的表面图,可用于合并。
然后我们定义一个“合并”规则,将两个或多个相邻的超平板空间合二为一:
- Hyperslab-spaces 只能组合成新的 hyperslab-spaces(因此您需要组合足够多的部分来创建新的 hyperslab,而不是一些更奇特的形状)
- 只需通过比较表面即可完成合并。如果存在具有匹配维度的特征,则将它们合并(因为很容易证明,如果特征匹配,合并 hyperslabs 总是比不合并更好)
现在这足以解决暴力问题。解决方案肯定是 NP 完全的。但是,我们可以添加一条额外的规则,它将显着降低此成本:“如果一个超平板空间覆盖相同的空间,并且在其表面上具有完全相同的特征,则认为它们比另一个‘更好’。在这种情况下,一个内部的 hyperslab 更少是更好的选择。”
现在这里的想法是,在算法的早期,您必须跟踪各种组合,以防万一它们最有用。然而,随着合并算法使事物变得越来越大,内部细节暴露在超平板空间表面上的可能性将变得越来越小。考虑
+===+===+===+---+---+---+---+
| : : A | X : : : :
+---+---+---+---+---+---+---+
| : : B | Y : : : :
+---+---+---+---+---+---+---+
| : : | : : : :
+===+===+===+ +---+---+---+
看看左边的方框,我冒昧地用更粗的线条标记了它。在将盒子与世界其他地方合并时,AB:XY 表面是最重要的。因此,只有少数几种合并模式可以出现在这个表面上
- 不能合并
- A:X 允许合并,但 B:Y 不允许
- B:Y 允许合并,但 A:X 不允许
- A:X 和 B:Y 都允许合并(两个独立的合并)
- 我们可以合并一个更大的正方形 AB:XY
有很多方法可以覆盖 3x3 方格(至少几十个)。但是,我们只需要记住实现每个合并过程的最佳方法。因此,一旦我们在动态规划中达到这一点,我们就可以忘记所有其他可能发生的组合,而只关注实现每组表面特征的最佳方法。
事实上,这为一个简单的贪心算法设置了问题,该算法探索哪种合并为减少超平板的数量提供了最佳承诺,始终记住实现给定表面特征集的最佳方法。当算法完成合并后,最终的 hyperslab-space 包含的内容就是最优布局。
我不知道它是否可证明,但我的直觉认为这将是一个 O(n^d) 算法,其中 d 是维数。我认为最坏的解决方案是一组超平板,当它们放在一起时,就形成了一个大的超平板。在这种情况下,我相信该算法最终会逆向 k-tree 算法。同样,没有给出任何证据……这只是我的直觉。