the * indicates the edges of the rects
the | indicates that a cell is "filled-in"
Notice that not all R*C cells are filled in, but only and exactly N cells
IF N=1, Sw=2, Sh=1 THEN R=1, C=1
********
*||||||*
********
IF N=2, Sw=2, Sh=1 THEN R=2, C=1
********
*||||||*
********
*||||||*
********
IF N=3, Sw=2, Sh=1 THEN R=2, C=2
***************
*||||||* *
***************
*||||||*||||||*
***************
IF N=4, Sw=2, Sh=1 THEN R=2, C=2
***************
*||||||*||||||*
***************
*||||||*||||||*
***************
IF N=5, Sw=2, Sh=1 THEN R=3, C=2
***************
*||||||* *
***************
*||||||*||||||*
***************
*||||||*||||||*
***************
# Implementation of AaronofTomorrow's answer
# implemented in python 2.6
# reasonable output
# works in constant time
import math
def f( N, Sw, Sh ) :
cols = math.sqrt( float(N) * float(Sh) / float(Sw) )
cols = round(cols)
rows = float(N) / float(cols)
rows = math.ceil(rows)
return (int(cols),int(rows))
# Another implementation inspired by Will's answer
# implemented in python 2.6
# reasonable output - a bit better in yielding more squarelike grids
# works in time proportional to number of rects
#
# strategy used it to try incrementaly adding a rect.
# if the resulting rect requires more space then two
# possibilities are checked - adding a new row or adding a new col
# the one with the best aspect ratio (1:1) will be chosen
def g( N, Sw, Sh ) :
slope = float(Sh)/float(Sw)
cols = 1
rows = 1
for i in xrange( N ) :
num_to_fit =i+1
allocated_cells= cols* rows
if ( num_to_fit <= allocated_cells ) :
pass # do nothing
else :
hc,wc = float(Sh * rows), float(Sw * (cols+1))
hr,wr = float(Sh * (rows+1)), float(Sw * cols)
thetac = math.atan( hc/wc)
thetar = math.atan( hr/wr)
alpha = math.pi/4.0
difr = abs(alpha-thetar)
difc = abs(alpha-thetac)
if ( difr < difc ) :
rows = rows +1
else:
cols = cols + 1
return (cols,rows)
答案 0 :(得分:2)
在Will Dean的回应的基础上,找到他的公式的衍生物(关于nCols):
-N * Sh / nCols + Sw
然后将其设置为0并求解nCols,得到:
nCols = sqrt(N * Sh / Sw)
回合那个,你应该有最佳的列数:
cols = round(sqrt(N * Sh / Sw))
rows = ceil(N / cols)
答案 1 :(得分:1)
我认为你会发现'最像方形'是迈向“最像圆圈”的一步,这是圆周(周长)最小的点。
你的周长是2 * nRows * Sh + 2 * nCols Sw。你知道nRows nCols&gt; = N,我认为将它简化为nRows * nCols = N在下一位就可以了。
如果不尝试,我认为你可以尝试找到函数的最小值:
N/nCols*Sh + nCols*Sw
Dunno,如果其中任何一个可以工作,但它有助于我将工作日的开始延迟5分钟,所以这不是一个死亡。
答案 2 :(得分:0)
如果矩形的数量是无限的,你需要找到Sw和Sh的LCD(最小公分母)。然后你可以将它除以Sw和Sh来找到水平和垂直计数。
由于它是有限的,它是不同的。我是否正确理解您必须使用所有矩形,结果也必须是矩形?我会这么认为。
在这种情况下,您对如何排列矩形并没有太多选择。只有那么多整数对在乘法时给出N.
在你的情况下,我会尝试找到所有可能的这样的整数对(使用一个简单的FOR循环)并查看哪一个最接近正方形。在FOR循环通知中,您必须仅检查sqrt(N),因为在此之后找到的每个整数对将与您已找到的整数对相同,只是相反。
答案 3 :(得分:0)
首先,特殊情况下的正方形矩形或矩形,其中维度为零。
否则,为了简化说明,请迭代地构建它:
add a new row until height is greater than width add a new column until width is greater than height
可能在代码中看起来像这样:
// place the first tile as an initialisation int tiles = num_tiles - 1; int rows = 1; int columns = 1; int width = sx; int height = sy; int i=1; // just because we're curious how many iterations we have // build the near-square while(tiles > 0) { while((tiles > 0) && ((width + sx) <= (height + sy))) { // add a column tiles -= rows; columns++; width += sx; i++; } while((tiles > 0) && ((height + sy) < (width + sx))) { // add a row tiles -= columns; rows++; height += sy; i++; } } // done printf("%d = %d (%dx%d) = %dx%d (%dx%d) in %d\n", num_tiles,tiles,sx,sy,rows,columns,width,height,i);
和一些结果:
100 = -5 (10x20) = 7x15 (150x140) in 21 1000 = -12 (10x20) = 22x46 (460x440) in 67 10000000 = -1628 (10x20) = 2236x4473 (44730x44720) in 6708 200 = 0 (7x13) = 10x20 (140x130) in 29 2000 = -13 (7x13) = 33x61 (427x429) in 93 20000000 = -3790 (7x13) = 3282x6095 (42665x42666) in 9376 400 = -14 (17x13) = 23x18 (306x299) in 40 4000 = -15 (17x13) = 73x55 (935x949) in 127 40000000 = -192 (17x13) = 7232x5531 (94027x94016) in 12762
最坏情况O(n),非常非常薄的矩形或少量矩形。但O(sqrt(n))在一般情况下?