Math 矩形内未知数字的最大平方大小

Math 矩形内未知数字的最大平方大小,math,tiles,max-size,Math,Tiles,Max Size,如果我有一组可以是任意数量的瓷砖(正方形),它们将填充一个未知大小的容器(矩形),我如何计算出瓷砖的最大尺寸,而不使任何瓷砖重叠 因此,如果我有两个瓷砖,矩形是100*100,那么最大瓷砖大小是50*50。如果矩形网格的大小为3或4个,则这也是最大的瓷砖大小,在本例中,矩形网格恰好是正方形 如果矩形是100*30,我有2块瓷砖,正方形的最大尺寸是30*30,如果我有4块瓷砖,最大尺寸是25*25 我如何通过编程来实现这一点,而不必通过各种可能的组合来占用处理器 我试着总结得更好一些, 我有一个

如果我有一组可以是任意数量的瓷砖(正方形),它们将填充一个未知大小的容器(矩形),我如何计算出瓷砖的最大尺寸,而不使任何瓷砖重叠

因此,如果我有两个瓷砖,矩形是100*100,那么最大瓷砖大小是50*50。如果矩形网格的大小为3或4个,则这也是最大的瓷砖大小,在本例中,矩形网格恰好是正方形

如果矩形是100*30,我有2块瓷砖,正方形的最大尺寸是30*30,如果我有4块瓷砖,最大尺寸是25*25

我如何通过编程来实现这一点,而不必通过各种可能的组合来占用处理器


我试着总结得更好一些, 我有一个:

矩形/边框,我需要尽可能多地填充,而不需要瓷砖重叠

我知道矩形的高度和宽度(但在运行期间可能会发生变化)

我有X个瓷砖(这可以在运行时更改),这些是正方形


所有瓷砖都不应重叠,每个瓷砖的最大尺寸是多少。它们的大小都相同。

您能详细说明一下如何定义填充吗?如果我按照你的描述(大If),你描述的许多案例似乎并没有填满矩形。例如,你说100*100矩形中的两个正方形是50*50。如果我正确理解您的配置,它们将被放置在这个矩形的“对角线”上。但在这个矩形中也会有两个50*50大小的“间隙”。这不是我认为的“填充”矩形。相反,我要说明的问题是,对于边界框为100*100(假设每个正方形必须与至少一个其他正方形接触)的2个(大小相等的正方形),最大的可能大小是多少

这里的关键点是,您的矩形似乎是一个边界框,而不是填充框


另外,你能为这个计算编写一个函数接口吗?给定边界框的尺寸,是否需要对n个可能的正方形执行此操作?

将较长的边除以平铺数。使用较短的一侧作为平铺尺寸。普雷斯托一块瓷砖

Rectagle = 200 x 10
Each tile is 10 x 10 (length of shorter side)
200/10 = 20 (number of tiles needed)
给定值:

N - number of tiles
a, b - sides of the rectangle
可以使用此函数计算瓷砖的侧面:

def maxSize(n: Int, a: Int, b: Int) = {
  var l = 0
  for (i <- 1 until a.min(b)) { // 
    val newL = (a.min(b) / i).min( (a.max(b) * i)/n )
    if (l < newL && ((a.min(b)/newL) * (a.max(b)/newL) >= n )  )
      l = newL
  }
  return l
}
然后从1列迭代到K列,其中

K = min(a, b)
对于每次迭代,使用以下公式计算瓷砖的新最大边

val newL = ( a.min(b) / i ).min( (a.max(b) * i)/n )
此公式取这两个值中的较小值:

1. min(a, b)/i -- maximum length of a tile if there are i columns in the smaller side of the rectangle
2. (i * max(a, b))/n -- maximum length of a tile if there are i columns and n tiles in the bigger side of the rectangle
如果候选newL大于初始值l,并且可以放置在正方形中而不重叠的最大可能瓷砖数量大于或等于瓷砖数量n,则

l = newL

在最后一次退货时,这是一个包装问题。最佳解决方案很难找到。例如,见

您可以通过将总曲面除以正方形数来计算(乐观)上界:
sqrt(width*height/n)

概念上:

  • 从一个正方形开始
  • 对于每一个额外的方块,如果你没有 到目前为止,你的网格框中有空间,收缩 现有的盒子只够 为额外的行或列留出空间
伪代码:给定M x N矩形,用K个正方形填充

// initial candidate grid within the rectangle
h=1
w=1
maxsquares=1
size=min(M,N) //size of the squares
while K > maxsquares
  if M/(h+1) >= N/(w+1)
    h=h+1
  else
    w=w+1
  endif
  maxsquares=h*w
  size=min(M/h,N/w)
done
print size
对于非常大的K,可能有更快的方法可以找到答案,但我想不出它们。如果您知道M和N是整数,可能会有更快的方法。

x=max(rectHeight/numberOfSquares,rectangleLength/numberOfSquares)
x = max(rectHeight/numberOfSquares, rectangleLength/numberOfSquares)

if x <= retangleHeight && x <= rectangleLength then
  squareSideLength = x
else
  squareSideLength = min(rectangleHeight, rectangleLength)

如果x以下函数计算给定信息的最大瓷砖尺寸

如果它是用Python编写的,这让您很难理解,请在评论中告诉我,我将尝试用其他语言来完成

import math
from __future__ import division

def max_tile_size(tile_count, rect_size):
    """
    Determine the maximum sized tile possible.

    Keyword arguments:
    tile_count -- Number of tiles to fit
    rect_size -- 2-tuple of rectangle size as (width, height)
    """

    # If the rectangle is taller than it is wide, reverse its dimensions
    if rect_size[0] < rect_size[1]:
        rect_size = rect_size[1], rect_size[0]

    # Rectangle aspect ratio
    rect_ar = rect_size[0] / rect_size[1]

    # tiles_max_height is the square root of tile_count, rounded up
    tiles_max_height = math.ceil(math.sqrt(tile_count))

    best_tile_size = 0

    # i in the range [1, tile_max_height], inclusive
    for i in range(1, tiles_max_height + 1):

        # tiles_used is the arrangement of tiles (width, height)
        tiles_used = math.ceil(tile_count / i), i

        # tiles_ar is the aspect ratio of this arrangement
        tiles_ar = tiles_used[0] / tiles_used[1]

        # Calculate the size of each tile
        # Tile pattern is flatter than rectangle
        if tile_ar > rect_ar:
            tile_size = rect_size[0] / tiles_used[0]
        # Tile pattern is skinnier than rectangle
        else:
            tile_size = rect_size[1] / tiles_used[1]

        # Check if this is the best answer so far
        if tile_size > best_tile_size:
            best_tile_size = tile_size

    return best_tile_size

print max_tile_size(4, (100, 100))

我假设正方形不能旋转。我敢肯定,如果允许你旋转它们,这个问题是很难解决的

我们从左上角开始,用正方形填充矩形。然后我们把正方形放在正方形的右边,直到我们到达矩形的右边,然后我们对下一行做同样的操作,直到我们到达底部。这就像在纸上写文章一样

请注意,永远不会出现右侧和底部都有空间的情况。如果在两个方向上都有空间,那么我们仍然可以增加正方形的大小

假设我们已经知道在第一行应该放置10个正方形,并且这非常适合宽度。则边长为
宽度/10
。因此,我们可以在第一列中放置
m=高度/边长
正方形。这个公式可以说我们可以在第一列中放置2.33个正方形。不可能放置0.33个正方形,我们只能放置2个正方形。真正的公式是
m=地板(高度/边长)

一个不是很快(但比尝试每种组合都快得多)的算法是尝试在第一行/列上首先放置一个正方形,然后看看是否可以在矩形中放置足够的正方形。如果它不起作用,我们尝试在第一行/列上放置两个正方形,等等,直到我们可以满足您想要的瓷砖数量

我认为存在一个O(1)算法,如果你被允许在O(1)中做算术,但我还没有弄明白它

这是这个算法的Ruby版本。如果矩形不是很薄,则该算法为O(sqrt(#of tiles))

def squareside(height, width, tiles)
  n = 0
  while true
    n += 1
    # case 1: the squares fill the height of the rectangle perfectly with n squares
    side = height/n
    m = (width/side).floor # the number of squares that fill the width
    # we're done if we can place enough squares this way
    return side if n*m >= tiles
    # case 2: the squares fill the width of the rectangle perfectly with n squares
    side = width/n
    m = (height/side).floor
    return side if n*m >= tiles
  end
end

您还可以使用二进制搜索来实现此算法。在这种情况下,它是O(log(#of tiles))。

我设法找到了一个“相对”最优的解决方案。部分基于Zac的伪代码答案

        //total number of tiles
        var tile_count : Number = numberOfSlides;
        //height of rectangle
        var b : Number = unscaledHeight;
        //width of rectanlge
        var a : Number = unscaledWidth;

        //divide the area but the number of tiles to get the max area a tile could cover
        //this optimal size for a tile will more often than not make the tiles overlap, but
        //a tile can never be bigger than this size
        var maxSize : Number = Math.sqrt((b * a) / tile_count);
        //find the number of whole tiles that can fit into the height
        var numberOfPossibleWholeTilesH : Number = Math.floor(b / maxSize);
        //find the number of whole tiles that can fit into the width
        var numberOfPossibleWholeTilesW : Number = Math.floor(a / maxSize);
        //works out how many whole tiles this configuration can hold
        var total : Number = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;

        //if the number of number of whole tiles that the max size tile ends up with is less than the require number of 
        //tiles, make the maxSize smaller and recaluate
        while(total < tile_count){
            maxSize--;
            numberOfPossibleWholeTilesH = Math.floor(b / maxSize);
            numberOfPossibleWholeTilesW = Math.floor(a / maxSize);
            total = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;
        }

        return maxSize;
//分幅的总数
var tile_count:Number=numberOfSlides;
//矩形高度
变量b:数值=无标度八;
//直肠宽度
变量a:数字=未标度宽度;
//将面积除以瓷砖数量,以获得瓷砖可以覆盖的最大面积
def squareside(height, width, tiles)
  n = 0
  while true
    n += 1
    # case 1: the squares fill the height of the rectangle perfectly with n squares
    side = height/n
    m = (width/side).floor # the number of squares that fill the width
    # we're done if we can place enough squares this way
    return side if n*m >= tiles
    # case 2: the squares fill the width of the rectangle perfectly with n squares
    side = width/n
    m = (height/side).floor
    return side if n*m >= tiles
  end
end
        //total number of tiles
        var tile_count : Number = numberOfSlides;
        //height of rectangle
        var b : Number = unscaledHeight;
        //width of rectanlge
        var a : Number = unscaledWidth;

        //divide the area but the number of tiles to get the max area a tile could cover
        //this optimal size for a tile will more often than not make the tiles overlap, but
        //a tile can never be bigger than this size
        var maxSize : Number = Math.sqrt((b * a) / tile_count);
        //find the number of whole tiles that can fit into the height
        var numberOfPossibleWholeTilesH : Number = Math.floor(b / maxSize);
        //find the number of whole tiles that can fit into the width
        var numberOfPossibleWholeTilesW : Number = Math.floor(a / maxSize);
        //works out how many whole tiles this configuration can hold
        var total : Number = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;

        //if the number of number of whole tiles that the max size tile ends up with is less than the require number of 
        //tiles, make the maxSize smaller and recaluate
        while(total < tile_count){
            maxSize--;
            numberOfPossibleWholeTilesH = Math.floor(b / maxSize);
            numberOfPossibleWholeTilesW = Math.floor(a / maxSize);
            total = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;
        }

        return maxSize;
int GetTileSize(int width, int height, int tileCount)
{
    // quick bailout for invalid input
    if (width*height < tileCount) { return 0; }

    // come up with an initial guess
    double aspect = (double)height/width;
    double xf = sqrtf(tileCount/aspect);
    double yf = xf*aspect;
    int x = max(1.0, floor(xf));
    int y = max(1.0, floor(yf));
    int x_size = floor((double)width/x);
    int y_size = floor((double)height/y);
    int tileSize = min(x_size, y_size);

    // test our guess:
    x = floor((double)width/tileSize);
    y = floor((double)height/tileSize);
    if (x*y < tileCount) // we guessed too high
    {
        if (((x+1)*y < tileCount) && (x*(y+1) < tileCount))
        {
            // case 2: the upper bound is correct
            //         compute the tileSize that will
            //         result in (x+1)*(y+1) tiles
            x_size = floor((double)width/(x+1));
            y_size = floor((double)height/(y+1));
            tileSize = min(x_size, y_size);
        }
        else
        {
            // case 3: solve an equation to determine
            //         the final x and y dimensions
            //         and then compute the tileSize
            //         that results in those dimensions
            int test_x = ceil((double)tileCount/y);
            int test_y = ceil((double)tileCount/x);
            x_size = min(floor((double)width/test_x), floor((double)height/y));
            y_size = min(floor((double)width/x), floor((double)height/test_y));
            tileSize = max(x_size, y_size);
        }
    }

    return tileSize;
}
for (width = 1 to 1000)
{
    for (height = 1 to 1000)
    {
        for (tileCount = 1 to 1000)
        {
            tileSize = GetTileSize(width, height, tileCount);

            // verify that increasing the tileSize by one
            // will result in too few tiles
            x = floor((double)width/(tileSize+1));
            y = floor((double)height/(tileSize+1));
            assert(x*y < tileCount);

            // verify that the computed tileSize actually
            // results in the correct tileCount
            if (tileSize > 0)
            {
                x = floor((double)width/tileSize);
                y = floor((double)height/tileSize);
                assert(x*y >= tileCount);
            }
        }
    }
}