平铺放置算法

时间:2014-01-31 14:25:05

标签: algorithm math block tile

我有这块瓷砖,宽36英尺36英寸,高。

36 x 36

所以我有块8x8,6x6,6x8,4x8可以旋转90度以适应任何可能的地方。 我的任务是制作应用程序来计算应该选择哪个和多少个块,以便所有块一起适合给定的墙壁oppening。在这个例子中,操作36 x 36。

注意:oppening应尽可能少地填充,这意味着更大的tile具有优先级

我应该使用哪种算法进行磁贴放置?

另一个例子。 Field 30 x 30绘制如下:

30 x 30

50 x 50

50 x 50

3 个答案:

答案 0 :(得分:1)

由于amit给了general case answer,我将特别提到这一点。使用这四个块大小,并假设它甚至可能(维度均匀且> = 6等),您可以使用半贪心算法:

第一个目标是最大化8x8块的数量。要做到这一点,您需要确定每个方向需要多少6个大小的块。对于每个维度,只需检查8的可除性。如果它不可分,则减去6.重复直到可以整除(它不应超过3次尝试)。

无论多少次,在这个维度上你需要6x6块。从它们中形成一个矩形并将其放在一个角落里。从8x8块中形成另一个矩形,并将它们放在对角。这两个矩形的角应该是触摸的。

所以现在你可能有一些剩余的空间,在对角的两个矩形的形式。我们知道每个维度的一个维度可以被8整除,一个维度可以被6整除。这里的简单方法是用适当的6x8块填充它,但这不会保证最大数量的大(8x8)块。例如,对于50x50,您将有两个18x32的矩形。你可以用12个6x8瓷砖填充它们。你甚至不能优于每个12块,但你可以在那里适应更多的8x8块。

如果这不是一个问题,那么你已经完成了(万岁)。这种方式的好处是你永远不需要使用4x8块。


如果你想要最大化8x8块,你将不得不采取另一个步骤。我们在这里专注于可被6整除的维度,因为8很容易。我们可能需要的每个尺寸(8x8,6x8,4x8)完美地堆叠在那里。

另一方面,它只有3个可能的数字:6,12和18.如果是其他任何东西,第一步没有做好。然后采取以下行动:

  • 对于6,添加一行6x8(无优化)
  • 对于12,添加一行4x8和一行8x8
  • 18,添加一行4x8,一行6x8,一行8x8

完成!


要看到差异,我们这里有两个50x50网格:

Blue  - 8x8
Red   - 6x6
Green - 6x8
Gray  - 4x8

basic

这个第一个例子给了我们49个总积木。蓝色是32x32区域(16个区块),红色是18x18(9个区块),其余的只是填充6x8(24个区块)。

better

此示例仍然总共提供了49个,但还有更多的8x8块。这里我们有24个大块,而不是最后一个例子中的16个。现在还使用了4x8块。

答案 1 :(得分:1)

在这里,你用Python:

def aux(x):
    # in h we store the pre-calculated results for small dimensions
    h = {18:[6,6,6], 16:[8,8], 14:[8,6], 12:[6,6], 10:[6,4], 8:[8], 6:[6], 4:[4]}
    res = []
    while x > 18: 
        # as long as the remaining space is large, we put there tiles of size 8
        res.append(8)
        x -= 8
    if x not in h:
        print("no solution found")
        return []

    return res + h[x]

def tiles( x, y ):
    ax = aux(x) # split the x-dimension into tiles
    ay = aux(y) # split the y-dimension into tiles
    res = [ [ (x,y) for x in ax ] for y in ay ]
    for u in res:
        print(u)
    return res


tiles( 30, 30 )

基本思想是你可以独立解决x和y,然后将两种解决方案结合起来。

编辑:正如Dukeling所说,这段代码很乐意使用4x6和4x4块,这与要求相反。但是,我认为只有在没有其他办法的情况下才会这样做。因此,如果结果包含这样的块,那么没有这些块就没有解决方案。如果您没有现成的Python,可以在此处使用此代码:http://ideone.com/HHB7F8,只需在源代码上方按 fork 即可。

答案 2 :(得分:0)

假设您正在寻找一般案例答案,我很遗憾地说 - 但这个问题是NP-Complete。它基本上是Subset Sum Problem的二维变体。

子集求和问题:给定一组S和一个数字x - 找出是否有S的子集加到x

很容易看出,通过将子集和问题减少到大小为1*x的“字段”以及s中的每个S,我们都有一个图块1*s - 解决一个问题也是另一个问题的解决方案。

因此 - 对这个问题没有已知的多项式解,并且大多数人认为不存在。
但请注意,这里也可以使用pseudo-polynomial dynamic programming solution to subset sum