单位立方体的边长,给定一个需要使用N个单位立方体来平铺/填充给定维度的

时间:2016-03-04 15:24:24

标签: algorithm math tiling

一个具有矩形棱柱3维空间,例如{xmin,xmax},{ymin,ymax},{zmin,zmax}。目标是使用最多N个立方体的预定义“网格”来最大化平铺3维空间。如果N不能均匀地平铺到空间中,它将使用不超过N个立方体。注意立方体位于立方体中心点(即它是网格),而不是立方体边缘。

例如,在N = 30的简单情况下,{0,3},{0,3},{0,3}。正确的答案是使用边长为1的立方体,在这种情况下,27个立方体将用于3行3列3堆中。

在N = 1000和{0,100},{0,0},{0,50}的更困难的情况下,显然y维仅使用1行立方体(它不能再使用),因此z和x尺寸必须使用以2:1的比例排列的1000个立方体。 100 / L * 50 / L = 1000.因此,边长可能在2.2361附近,因为22 x 1 x 45 = 990是我们最接近1000的距离(或者,我们已经将我们能够扩展的范围最小化了没有覆盖我们的立方体中心)。当然,边必须是整数的立方体。

我正在尝试制定一个方程组来解决这个问题,但我有一种奇怪的感觉,这是一个满足(最小化)问题,因此需要进行一些迭代......这是一个尝试无论如何,方程组:

L, xe, ye, ze ∊ Positive Reals
N, x, y, z ∊ Natural Numbers
x*y*z ≤ N
(x-1)*L ≤ xe
(y-1)*L ≤ ye
(z-1)*L ≤ ze
x,y,z ≥ 1
L = min(i) { (xe*ye*ze) - ((x-1)*i*(y-1)*i*(z-1)*i) }

我这样做是因为它是x-1,y-1等,意味着它们可以超出宽度,最多只有1个立方体大小。我无法确定在所有维度上执行此操作是否正确,或者指定它必须在最多一个维度(最小的?)之外。

1 个答案:

答案 0 :(得分:1)

一般想法

这里的直觉是每个方向上立方体的数量将与该方向上的空间大小成比例,因为立方体是规则的。对此的另一个暗示是问题的解决方案"每个方向有多少立方体"只取决于尺寸之间的比例,而不是它们的实际值:如果你将每个尺寸乘以相同的扩张系数,你的解决方案仍然是相同的。

简化问题

假设您的空间大小为dx, dy, dz,全部为非零,并且您希望最多使用N个多维数据集。

让我们将约束表达为:

  

找到Nx,Ny,Nz,L这样的    - Nx * Ny *Nz≤N
   - Nx *L≤dx
   - Ny *L≤dy
  最大限度地减少"丢失音量":(dx * dy * dz - L^3 * Nx * Ny * Nz)

您可能希望最大化Nx * Ny * Nz。另请注意,最小化未平铺的音量等同于最大化L^3 * Nx * Ny * Nz

最后一个观察结果是,如果您的解决方案在任何方面都是最佳的(立方体数量或平铺量),则至少有一个维度将具有相等N@ * L == d@,否则我们可能会增加L

让我们假设dx是这个维度而不失一般性,让我们将所有长度除以dx,因此a@ = d@ / dx @y z }和ax = 1(以及dx^3 * (Ny / Nx) * (Nz / Nx),如果需要)。然后我们可以重写这个问题:

  

找到Nx,Ny,Nz,L这样的    - Nx * Ny *Nz≤N
   - Nx = dx / L
   - Ny /Nx≤ay
   - Nz /Nx≤az
  最大化立方体'卷:Nx * Ny * Nz ≤ N

因此,您的问题是如何在保持N = 1000的同时,尽可能接近每个方面的立方体数量比率,这与您本能地接近Nx的方式相同情况下。

算法建议:例如,您可以迭代地增加N@ = floor(a@ * Nx)并在{y,z} Nx * Ny * Nz ≤ N中为@设置ay,同时保留最佳解决方案。

最佳解决方案

请注意,如果您的比率aza@ = n@ / m@是合理的,就像您的示例中一样,可以很容易地找到最小化的精确解决方案。

让我们在{y,z}中为@编写Nx = lcm(my, mz),然后我们可以通过设置为dx, dy, dz - 分母的最小公倍数来找到一个精确的解。请注意,在Nx = dx / gcd(dx, dy, dz)都是整数的情况下,这意味着Nx^3 * ax * ay = lcm(my, mz) ^3 * ny * nz / (my * mz) ≤ N

因此,如果N,此解决方案也适合Nx = lcm(my, mz) L = dx / Nx Ny = Nx * ay Nz = Nx * az 的约束。要完整地写出来:

ay = az = 1

在您的示例中,对于3D案例,您有Nx = Ny = Nz = 1az = 1/2的解决方案,而对于2D案例,我们只有维度x,z和Nx = 2,这个你有Nz = 1Nx * Ny * Nz ≤ N

的解决方案

现在您可以添加更多多维数据集,因为floor(cbrt(N / (Nx * Ny * Nz)))约束中有很多松弛。特别是,您可以将每个坐标乘以floor(cbrt(30 / 1)) = 3,在第一种情况下为floor(sqrt(1000 / 2)) = 22,在2D情况下为Nx

总结您的示例的结果:

  

空间= {3,3,3} N = 30:Nx = 3,Ny = 3,Nz = 3,L = 1   space = {100,50} N = 1000:Nx = 44,Nz = 22,L = 2.72727272 ...

启发式(S)

如果我们无法找到确切的答案,我们可以做出有根据的猜测。为了不迭代(Ny / Nx) * (Nz / Nx)值,或者只是为了进行合理的初始猜测。

请注意,分母越大,具有相同分母的两个分数之间的间隔越小。这并不意味着给定一个想要近似的实数,近似的精度与分母的大小成正比,但是当逼近大量实数时的平均精度会更好(因此,你在单个案例中的概率更高了。)

我们正在尝试最大化ay,因此,根据我们对az(N@ + 1) / Nx ≥ a@的约束,我们得到N@ ≥ a@ * Nx - 1,因此Nx * Ny * Nz ≤ N。 现在,Nx因此Nx * (Nx * ay - 1) * (Nx * az - 1) ≤ N上的界限是:
N@ ≥ a@ * Nx - 1 ≥ a@ * Nx

但我懒得解决这个问题,所以让我们甚至简化一些事情:Nx * (Nx * ay) * (Nx * az) ≤ N
因此:Nx = floor(crbt(N / (ay * az))) L = dx / Nx Ny = floor(Nx * ay) Nz = floor(Nx * az)

所以你可以先尝试一下:

Nx = floor(crbt(N * dx * dx / (dy * dz)))
L  = dx / Nx
Ny = floor(dy / L)
Nz = floor(dz / L)

或(完全相同的事情,没有a @):

Nx

如果您想确保拥有最佳值,可能需要尝试查看简化是否过多限制Nx * Ny * Nz ≥ N,因此将其递增到Nx并保持最佳配置。< / p>

同样,Nx * ay的不同值可能会使Nx * azNx更接近其整数部分,从而浪费更少的空间。您可以递减Nx直到它很小。请注意,您可以跳过任何除以您已经尝试过的x值的值。

选择&#34;填充维度&#34; x

仍然选择哪个方向x - 本能地我会说你的空间是最大的维度,但这又是一个启发式,如果你想要最佳答案你会有尝试所有方向。

虽然在确切的解决方案中,侧面尺寸比率是合理的,但选择任何一边为{{1}}都可以,因为所有尺寸都将被填充。