假设我们有一个网格,并且我们希望使用尽可能少的颜色在其上绘制矩形区域,每个区域一个。
有些单元格已经被涂成黑色,不能被涂满:
是否有多项式算法可以解决此问题?
经过测试,我发现这种情况的解决方案是9(因为我们需要9种不同的颜色来绘制最小数量的区域来填充整个网格)
贪婪的方法似乎效果很好:只是搜索具有最大(白色)区域的矩形并绘制它,重复此过程直到没有其他要绘制的东西,但我没有测量复杂性或正确性。
>答案 0 :(得分:4)
以下是一些可以在特定情况下简化此问题的观察结果。首先,可以将相邻的相同行和列简化为一个行或一列,而无需更改所需的区域数,以形成简化的网格:
一个简化的网格,其中没有将行或列划分为两个以上的无色部分(即具有两个或多个独立的黑色单元),可以通过将行或列用作区域来找到最佳解决方案(取决于是否网格的宽度或高度更大):
然后区域的数量为最小(宽度,高度)+黑色单元的数量。
如果简化网格中的边框行或边框不包含黑色单元格,那么将其用作区域始终是最佳解决方案;将其某些部分添加到其他区域将需要在边框的行或列中至少创建一个额外的区域(取决于相邻行或列中黑色单元格的数量):
这意味着可以通过删除没有黑格的边框行和列,并将删除的区域数添加到区域计数中来进一步简化网格:
类似地,如果一个或多个边界单元被相邻行或列中的黑色单元隔离,则所有连接的未着色相邻单元都可以视为一个区域:
您可以随时回到以前的规则;例如在上例中将最右边和最左边的列转换为区域之后,我们剩下下面的网格,可以使用第一条规则进行简化,因为底部的两行相同:
折叠相同的相邻行或列也可以局部应用于网格的隔离部分。下面的示例没有相同的相邻行,但是中间部分是孤立的,因此第3到第6行可以折叠:
在左边的第3行和第4行可以局部折叠,在右边的第5行和第6行,因此我们得出了上面第三张图中的情况。这些塌陷的细胞然后充当一个。
一旦使用上述规则找不到任何进一步的简化,并且您想要检查网格(部分)的每个可能的划分,第一步可能是列出可以使用网格进行的最大矩形尺寸。相应的单元格作为其左上角;对于上面第一个示例中的简化6x7网格,应为:
COL.1 COL.2 COL.3 COL.4 COL.5 COL.6
ROW 1 [6x1, 3x3, 1x7] [5x1, 2x3] [4x1, 1x7] [3x1] [2x5] [1x7]
ROW 2 [3x2, 1x6] [2x2] [1x6] [] [2x4] [1x6]
ROW 3 [6x1, 1x5] [5x1] [4x3, 2x5] [3x3, 1x5] [2x3] [1x5]
ROW 4 [1x4] [] [4x2, 2x4] [3x2, 1x4] [2x2] [1x4]
ROW 5 [6x1, 4x3] [5x1, 3x3] [4x1, 2x3] [3x1, 1x3] [2x1] [1x3]
ROW 6 [4x2] [3x2] [2x2] [1x2] [] [1x2]
ROW 7 [6x1] [5x1] [4x1] [3x1] [2x1] [1x1]
然后,您可以使用这些最大大小为每个单元格生成每个选项;例如对于单元格(1,1),它们应为:
6x1, 5x1, 4x1, 3x3, 3x2, 3x1, 2x3, 2x2, 2x1, 1x7, 1x6, 1x5, 1x4, 1x3, 1x2, 1x1
(列表中的某些矩形大小可以跳过;例如,在不添加第四个孤立单元格以获得4x1的情况下,使用3x1大小的区域永远没有意义。)
选择一个选项后,您将跳过所选矩形所覆盖的单元格,并尝试下一个单元格的每个选项,依此类推...
在大型网格上运行此选项将导致大量的op选项。但是,在每一点上您都可以返回检查简化规则是否可以帮助您。
要查看首先选择最大矩形的贪婪算法不能保证最优解,请考虑以下示例。在中间选择2x2正方形将导致具有5个区域的解决方案,而存在仅具有4个区域的几个解决方案。