矩形内未知数的最大正方形尺寸
如果我有一组可以是任意数量的图块(正方形),并且它们要填充未知大小的容器(矩形),我如何计算出图块的最大尺寸而不使它们重叠。
因此,如果我有 2 个图块且矩形为 100 * 100,则最大图块尺寸为 50 * 50。如果此大小的矩形有 3 或 4 个图块,这也将是图块的最大尺寸,而这种情况恰好发生在这个例子中是一个正方形。
如果矩形是 100 * 30 并且我有 2 个图块,则正方形的最大尺寸将为 30 * 30,如果我有 4 个图块,则最大尺寸将为 25 * 25。
如何以编程方式执行此操作而不占用处理器尝试每一种可能的组合。
我试着总结得更好一些 我有一个:
矩形/边界框,我需要在不重叠瓷砖的情况下尽可能多地填充它。
我知道矩形的高度和宽度(但这可能在运行时改变)。
我有 X 个图块(这可以在运行时更改),这些是正方形。
任何图块都不应重叠,每个图块的最大尺寸是多少。 它们的尺寸都相同。
If I have a set of tiles (squares) which can be any number and they are to fill a container (rectangle) of an unknown size how do I work out the maximum size of the tiles without having any of them overlap.
So if I have 2 tiles and the rectangle is 100 * 100 then the max tile size is 50 * 50. This would also be the max size of tile if there was 3 or 4 tiles for this size of rectanlgle, which just so happens to be a square in this example.
If the rectanlge was 100 * 30 and I had 2 tiles, the max size of the square would be 30 * 30, if I have 4 tiles the max size would be 25 * 25.
How can I do this programatically without hogging the processor by going through every possible combination.
I try to summarise a bit better,
I have a:
rectangle/bounding box that I need to fill as much as possible without the tiles overlapping.
I know the height and width of the rectangle (but this can change during runtime).
I have X number of tiles (this can change at run time), these are squares.
None of the tiles should overlap, what is the maximum size that each tile can be. They are all to be the same size.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
从概念上讲:
到目前为止,你的网格框中的空间,缩小
现有的盒子足以制作
额外的行或列的空间。
伪代码:给定 M x N 矩形来填充 K 正方形
对于非常大的 K,可能有更快的方法来跳转到答案,但我想不出它们。 如果您知道 M 和 N 是整数,可能会有更快的方法。
Conceptually:
room in your grid box so far, shrink
the existing box just enough to make
room for an additional row or column.
pseudocode: given M x N rectangle to fill with K squares
There are probably faster ways to jump to the answer for very large K, but I can't think of them. If you know that M and N are integers, there may be even faster methods.
这是一个没有循环的 O(1) 解决方案。
使用矩形的纵横比(高度/宽度),您可以初步猜测 x 和 y 方向上的图块数量。 这给出了图块总数的上限和下限:在 xy 和 (x+1)(y+1) 之间。
基于这些界限,存在三种可能性:
我使用以下代码针对 1 到 1000 之间的所有整数宽度、高度和tileCounts 测试了该函数:
Here is an O(1) solution with no loops.
Using the aspect ratio (height/width) of the rectangle, you can come up with an initial guess at the number of tiles in the x and y directions. This gives an upper and lower bound for the total number of tiles: between xy and (x+1)(y+1).
Based on these bounds, there are three possibilities:
I have tested this function for all integer widths, heights and tileCounts between 1 and 1000 using the following code:
这是一个包装问题。 最佳解决方案很难找到。 例如,请参阅将 N 个正方形打包在一个正方形中。
您可以通过将总表面积除以正方形数量来计算(乐观)上限:
sqrt(width*height/n)
。This is a packing problem. Optimal solutions are hard to find. See for example Packing N squares in a square.
You can compute an (optimistic) upper bound by dividing the total surface by the number of squares:
sqrt(width*height/n)
.我设法想出了一个“相对”最优的解决方案。 部分基于扎克的伪代码答案。
其作用是计算出矩形的总面积,然后除以所需的瓷砖数量。 由于每个图块都是一个正方形,我可以对其进行平方,以便获得最佳图块的最大尺寸。
有了这个最佳尺寸,我就会检查宽度和宽度可以容纳多少块整块瓷砖。 高度。 将它们相乘,如果小于所需的图块数量,则减小最佳尺寸并再次执行检查,直到所有图块都适合矩形。
我可以通过执行诸如每次将最佳大小减少 -2 代替 -1 之类的操作来进一步优化此操作,然后如果所有图块都适合则增加 1,以确保我没有错过有效大小。 或者我可以跳回超过-2,比如说-10,然后如果它们所有的瓷砖适合增加5,那么如果不适合减少-2等等,直到我得到最佳适合。
查看http://kennethsutherland.com/flex/stackover/SlideSorterOK.html我的例子。
感谢您提供的所有各种信息。
I've managed to come up with a 'relatively' optimal solution. Partially based on Zac's pseudocode answer.
What this does is to work out the total area of the rectanlge, then divide it by the required number of tiles. As each tile is a square I can SQRT this so that I get the max size of the optimal tile.
With this optimal size I then check to see how many WHOLE tiles I can fit into the width & height. Multiply these together and if it is less than the required number of tiles then I reduce the optimal size and perform the checking again until all of the tiles fit the rectanlge.
I could optimise this further by doing something like reduce the optimal size by -2 insted of -1 each time and then if all the tiles fit increase by 1 just to make sure that I've not missed a valid size. or I could jump back more than -2, say -10 then if they all tiles fit increase by 5, then if the don't fit reduce by -2 etc until I get an optimal fit.
Check out http://kennethsutherland.com/flex/stackover/SlideSorterOK.html for my example.
Thanks for all the various info.
以下函数计算给定信息的最大尺寸图块。
如果它是用 Python 编写的,这让您难以理解,请在评论中告诉我,我会尝试用其他语言来完成它。
该算法可以大致描述如下:
tiles_max_height
。)这可能是此处列出的更快的算法之一,因为它计算 n 的最佳正方形大小 O(sqrt(n)) 瓷砖。
更新
经过进一步考虑,这个问题在上面的解决方案的基础上有了更简单的解决方案。 假设你有 30 块瓷砖。 您可能的图块排列很容易计算:
假设您的矩形为 100 x 60。您的矩形的纵横比为 1.6667。 该值介于 1.2 和 2 之间。现在,您只需计算 8 x 4 和 6 x 5 排列的图块大小。
不过,从技术上讲,第一步仍然需要 O(sqrt(n)),因此这个更新的方法并不比第一次尝试渐近更快。
评论区的一些更新
The following function calculates the maximum-sized tile for the given information.
If the fact that it's written in Python makes it hard for you to understand, let me know in a comment and I'll try to do it up in some other language.
The algorithm can loosely be described as follows
tiles_max_height
in code.)This is probably one of the faster algorithms listed here, as it computes the best square size in O(sqrt(n)) for n tiles.
Update
On further consideration, this problem has a simpler solution based on the solution above. Say you are given 30 tiles. Your possible tile arrangements are easy to compute:
Say your rectangle is 100 x 60. Your rectangle's aspect ratio is 1.6667. This is between 1.2 and 2. Now, you only need to calculate the tile sizes for the 8 x 4 and the 6 x 5 arrangements.
The first step still technically takes O(sqrt(n)) though, so this updated method is not asymptotically faster than the first attempt.
Some updates from the comments thread
您能详细说明一下您如何定义填充吗? 如果我按照你的描述(大如果),似乎你描述的许多情况实际上并没有填充矩形。 例如,您说 100*100 矩形中的 2 个正方形将是 50*50。 如果我正确理解你的配置,它们将被放置在这个矩形的“对角线”上。 但在该矩形中也会有两个大小为 50*50 的“间隙”。 这不是我所认为的“填充”矩形。 相反,我会将问题表述为 2 个(大小相等的正方形)的最大可能尺寸是多少,其边界框为 100*100(假设每个正方形必须与至少一个其他正方形接触?)。
这里的关键点是你的矩形似乎是一个边界框并且没有填充。
另外,你能为这个计算编写一个函数接口吗? 给定边界框的尺寸,您是否需要对 n 个可能的正方形执行此操作?
Could you elaborate on how you define fill? If I follow your description (big if) it seems that many of the cases you describe don't actually fill the rectangle. For example, you say 2 squares in a 100*100 rectangle would be 50*50. If I understand your configuration correctly, they would be placed on the "diagonal" of this rectangle. But then there would be two "gaps" of size 50*50 in that rectangle as well. That isn't what I think of as "filling" the rectangle. I would instead state the problem as what is the largest possible size for 2 (equal sized squares) whose bounding box would be 100*100 (assuming that every square had to be in contact with at least one other square?).
The key point here is that your rectangle seems to be a bounding box and not filled.
Also, can you write a functional interface for this calculation? Do you need to do it for n possible squares given the dimensions of the bounding box?
给定值:
可以使用以下函数计算图块的边:
我假设您不会制作小于 1x1 的图块,无论 1 的度量是什么,
首先您从大小 0 开始:
然后从 1 迭代到 K瓦片的列,
其中每次迭代使用此公式计算瓦片的新最大边,
此公式采用这两个值中较小的一个:
如果候选 newL 大于初始值 l 和可以放入的瓦片的最大可能数量没有重叠的正方形大于或等于瓷砖数量 n 然后
最后返回 l
Given values:
side of a tile may be calculated using this function:
i have supposed that you are not going to make tiles smaller than 1x1, whatever the measure of 1 is
first you start from the size 0:
then you iterate from 1 to K columns of tiles where
for every iteration calculate new maximum side of a tile using this formula
this formula takes the smaller on of these two values:
if the candidate newL is greater than the initial value l and maximum possible number of tiles which can be put in the square without overlaping is greater or equal than number of tiles n then
on the end return l
我认为正方形不能旋转。 我很确定,如果允许轮换它们,这个问题会非常困难。
因此,我们从左上角开始用正方形填充矩形。 然后我们将正方形放在该正方形的右侧,直到到达矩形的右侧,然后对下一行执行相同的操作,直到到达底部。 这就像在纸上书写文字一样。
请注意,永远不会出现右侧和底部有剩余空间的情况。 如果两个方向都有空间,那么我们仍然可以增加正方形的大小。
假设我们已经知道第一行应该放置 10 个正方形,并且这完全适合宽度。 那么边长就是
width/10
。 因此我们可以在第一列中放置m = height/sidelength
正方形。 这个公式可以说我们可以在第一列放置 2.33 个正方形。 不可能放置 0.33 个方格,我们只能放置 2 个方格。 真正的公式是m = Floor(高度/边长)
。一个不太快(但比尝试每种组合快得多)的算法是尝试首先在第一行/列上放置 1 个正方形,然后看看我们是否可以在矩形中放置足够的正方形。 如果它不起作用,我们会在第一行/列上尝试 2 个正方形,依此类推,直到我们可以容纳您想要的图块数量。
我认为如果允许在 O(1) 中进行算术运算,则存在 O(1) 算法,但到目前为止我还没有弄清楚。
这是该算法的 Ruby 版本。 如果矩形不是很薄,则此算法的复杂度为 O(sqrt(# oftiles))。
您还可以使用二分搜索来实现此算法。 在这种情况下,它的复杂度为 O(log(图块数))。
I assume that the squares can't be rotated. I'm pretty sure that the problem is very hard if you are allowed to rotate them.
So we fill the rectangle by squares by starting in the left-top corner. Then we put squares to the right of that square until we reach the right side of the rectangle, then we do the same with the next row until we arrive at the bottom. This is just like writing text on paper.
Observe that there will never be a situation where there's space left on the right side and on the bottom. If there's space in both directions then we can still increase the size of the squares.
Suppose we already know that 10 squares should be placed on the first row, and that this fits the width perfectly. Then the side length is
width/10
. So we can placem = height/sidelength
squares in the first column. This formula could say that we can place 2.33 squares in the first column. It's not possible to place 0.33 of a square, we can only place 2 squares. The real formula ism = floor(height/sidelength)
.A not very fast (but A LOT faster than trying every combination) algorithm is to try to first place 1 square on the first row/column, then see if we can place enough squares in the rectangle. If it doesn't work we try 2 squares on the first row/column, etc. until we can fit the number of tiles you want.
I think there exists an O(1) algorithm if you are allowed to do arithmetic in O(1), but I haven't figured it out so far.
Here's a Ruby version of this algorithm. This algorithm is O(sqrt(# of tiles)) if the rectangle isn't very thin.
You can also use binary search for this algorithm. In that case it's O(log(# of tiles)).
将长边除以瓷砖数量。 使用较短的一侧作为瓷砖尺寸。 急! # 瓷砖。
Divide the longer side by the number of tiles. Use the shorter side as the tile size. Presto! # of tiles.