尽可能扩展矩形以覆盖另一个矩形,最大限度地减少重叠

时间:2018-03-20 13:21:54

标签: algorithm geometry rectangles

给定一个平铺的,x和y对齐的矩形和(可能)一组可能重叠的起始矩形,我想找到一组矩形,以便:

  • 如果不存在起始矩形,则可以创建一个;否则不要创建额外的矩形
  • 起始集中的每个矩形尽可能地扩展
  • 重叠最小
  • 覆盖整个平铺的矩形区域。

这闻起来很像套装问题,但它仍然是......不同。

关键是每个起始矩形区域必须最大化,同时仍然最小化一般重叠。一个好的解决方案可以在必要的重叠和高的初始矩形大小之间保持平衡。

我建议评级功能,例如: \left( \left( \sum\limits_{n=0}^{initial_boxes_count-1}{{box_area}_n} \right) \times extended_initial_rectangles_count \right) - \left( \sum\limits_{n=0}^{{overlapping_boxes_count}-1}{number_of_overlaps} \right)

越高越好。

示例(假设矩形平铺为4x4网格;平铺中的数字表示起始矩形" ID"):

  • 最简单的情况:没有提供起始矩形,只需创建一个并完全展开:

    .---------------.      .---------------.
    |   |   |   |   |      | 1 | 1 | 1 | 1 |
    |---|---|---|---|      |---|---|---|---|
    |   |   |   |   |      | 1 | 1 | 1 | 1 |
    |---|---|---|---|  =>  |---|---|---|---|
    |   |   |   |   |      | 1 | 1 | 1 | 1 |
    |---|---|---|---|      |---|---|---|---|
    |   |   |   |   |      | 1 | 1 | 1 | 1 |
    ·---------------·      ·---------------·
                           rating: 16 * 1 - 0 = 16
    
  • 更复杂:

    .---------------.      .---------------.      .---------------.
    | 1 | 1 |   |   |      | 1 | 1 | 1 | 1 |      | 1 | 1 | 2 | 2 |
    |---|---|---|---|      |---|---|---|---|      |---|---|---|---|
    | 1 | 1 |   |   |      | 1 | 1 | 1 | 1 |      | 1 | 1 | 2 | 2 |
    |---|---|---|---|  =>  |---|---|---|---|  or  |---|---|---|---|
    |   |   | 2 | 2 |      | 2 | 2 | 2 | 2 |      | 1 | 1 | 2 | 2 |
    |---|---|---|---|      |---|---|---|---|      |---|---|---|---|
    |   |   | 2 | 2 |      | 2 | 2 | 2 | 2 |      | 1 | 1 | 2 | 2 |
    ·---------------·      ·---------------·      ·---------------·
             ratings:     (4 + 4) * 2 - 0 = 16   (4 + 4) * 2 - 0 = 16
    
  • 非常糟糕的情况,初始重叠:

    .-----------------.      .-----------------------.
    | 1   |   |   |   |      |  1  |  1  |  1  |  1  |
    |-----|---|---|---|      |-----|-----|-----|-----|
    | 1,2 | 2 |   |   |      | 1,2 | 1,2 | 1,2 | 1,2 |
    |-----|---|---|---|  =>  |-----|-----|-----|-----|
    |     |   |   |   |      |  2  |  2  |  2  |  2  |
    |-----|---|---|---|      |-----|-----|-----|-----|
    |     |   |   |   |      |  2  |  2  |  2  |  2  |
    ·-----------------·      ·-----------------------·
        rating: (8 + 12) * 2 - (2 + 2 + 2 + 2) = 40 - 8 = 36
    
        covering with 1 only:
                             .-----------------------.
                             |  1  |  1  |  1  |  1  |
                             |-----|-----|-----|-----|
                             | 1,2 | 1,2 |  1  |  1  |
                         =>  |-----|-----|-----|-----|
                             |  1  |  1  |  1  |  1  |
                             |-----|-----|-----|-----|
                             |  1  |  1  |  1  |  1  |
                             ·-----------------------·
        rating: (16 + 2) * 1 - (2 + 2) = 18 - 4 = 16
    
  • 更多起始矩形,也重叠:

    .-----------------.      .---------------------.
    | 1 | 1,2 | 2 |   |      | 1 | 1,2 | 1,2 | 1,2 |
    |---|-----|---|---|      |---|-----|-----|-----|
    | 1 |  1  |   |   |      | 1 |  1  |  1  |  1  |
    |---|-----|---|---|  =>  |---|-----|-----|-----|
    | 3 |     |   |   |      | 3 |  3  |  3  |  3  |
    |---|-----|---|---|      |---|-----|-----|-----|
    |   |     |   |   |      | 3 |  3  |  3  |  3  |
    ·-----------------·      ·---------------------·
        rating: (8 + 3 + 8) * 3 - (2 + 2 + 2) = 57 - 6 = 51
    

起始矩形可以位于平铺矩形中的任何位置,并且具有任何大小(最小边界1个平铺)。

目前起始网格可能大到33x33,但未来可能更大。

我还没有能够将这个问题的实例化减少到一个问题,但这可能只是我自己的无能。

我目前以有效的方式解决这个问题的方法是这样的:

if list of starting rects empty:
  create starting rect in tile (0,0)
for each starting rect:
  calculate the distances in x and y direction to the next object (or wall)
sort distances in ascending order
while free space:
  pick rect with lowest distance
  expand it in lowest distance direction

我不确定这是否能提供最佳解决方案,或者确实是最有效的解决方案......当然,如果存在边缘情况,这种方法会失败。

1 个答案:

答案 0 :(得分:1)

建议的攻击。你的旅费可能会改变。欧盟以外的运输成本更高。

  • 制作打开的瓷砖列表
  • 制作一个矩形列表(尺寸和角落)

我们将尝试进行+1个增长步骤:在选定的方向上展开一个矩形的单位。在每次迭代中,找到得分最高的+1。迭代直到覆盖整个房间(大矩形)。

评分建议:

  • 计算扩展名添加的正方形:空心方块为+1;对于每个其他矩形重叠,占用的正方形为-1。

例如,在这个起始位置:

-  -  3  3
1  1 12  -
-  -  2  -

...如果我们尝试将矩形3向下延伸一行,我们会在右边的空方块中获得+1,但在重叠12时获得-2

  • 将此分数除以当前矩形区域。在上面的示例中,我们将(+1 - 2)/(1 * 2)或-1/2作为该移动的得分......可能不是一个好主意。

整个第一次迭代会考虑下面的动作;方向是上下左右

rect  dir  score
  1    U   0.33 = (2-1)/3
  1    D   0.33 = (2-1)/3
  1    R   0.33 = (1-0)/3
  2    U  -0.00 = (0-1)/2
  2    L   0.00 = (1-1)/2
  2    R   0.50 = (2-1)/2
  3    D   0.00 = (1-1)/2
  3    L   0.50 = (1-0)/2

我们有一个最佳得分平局:2 R和3 L.我将添加一个较小的标准,即采用更大的扩展,2个平铺超过1.这给出了:

-  -  3  3
1  1 12  2
-  -  2  2

第二次迭代:

rect  dir  score
  1    U   0.33 = (2-1)/3
  1    D   0.33 = (2-1)/3
  1    R   0.00 = (0-1)/3
  2    U  -0.50 = (0-2)/4
  2    L   0.00 = (1-1)/4
  3    D  -1.00 = (0-2)/2
  3    L   0.50 = (1-0)/2

当然,上次的领带现在是唯一的首选,因为两者没有冲突:

-  3  3  3
1  1 12  2
-  -  2  2

可能的优化:如果+1没有重叠,请在计算得分之前尽可能地扩展(避免重叠)。

在最后两次迭代中,我们将同样获得3 L和1 D作为我们的选择,以

结束
3  3  3  3
1  1 12  2
1  1  2  2

请注意,此算法将为您的"非常糟糕的示例获得相同的答案":此算法将覆盖整个房间2,仅减少到2个重叠方块。如果你想在这种情况下扩展1,我们需要一个因子来表示你所覆盖的另一个矩形的比例,而不是我的常数值1。

这看起来像是一个易处理的起点吗?