Ruby,228个字节* 21895 = 4992060
->n{a=(0..n*2).map{$b=' '*n}
g=0
m=n*2
(n**0.5).to_i.downto(1){|i|n%i<1&&(m=[m,n+h=n/i].min
g+=h+1
g<m+2?(a[g-h-1,1]=(1..h).map{?**i+$b}):(x=(m-h..m).map{|j|r=a[j].rindex(?*);r ?r:0}.max
(m-h+1..m).each{|j|a[j][x+2]=?**i}))}
a}
与未发布的代码相比有几处更改。最大的变化是变量的含义m
从最方形的高度到方形的高度加n
。
琐碎地,*40
已更改为*n
,这意味着在适当的地方有很多不必要的空格n
。并-2
更改为0
,这意味着在底部绘制的矩形始终会漏掉前两列(这导致仅分解为的数字的包装较差(n/2)*2
)
说明
我终于找到时间了。
对于给定n
的最小字段,必须为最长的矩形1*n
和最大的矩形都具有足够的空间x*y
。显然,如果两个矩形的长边朝向相同方向,则可以实现最佳布局。
忽略矩形之间对空格的要求,我们发现总面积为(n+y)*x = (n+n/x)*x
或n*(x+1)
。无论哪种方式,此计算结果均为n*x + n
。包括空格,x
如果我们将矩形首尾相连放置,或者n
如果将矩形并排放置,则必须包含一个额外的空格。因此,前者是优选的。
这为(n+y+1)*x
字段区域提供了以下下限:
n area
60 71*6=426
111 149*3=447
230 254*10=2540
400 421*20=8240
480 505*20=10100
这建议以下算法:
Find the value (n+y+1) which shall be the field height
Iterate from the squarest rectangle to the longest one
While there is space in the field height, draw each rectangle, one below the other, lined up on the left border.
When there is no more space in the field height, draw the remaining rectangles, one beside the other, along the bottom border, taking care not to overlap any of the rectangles above.
(Expand the field rightwards in the rare cases where this is necessary.)
实际上可以在上述下限范围内获得所需测试用例的所有矩形,但60除外,它给出以下71 * 8 = 568的输出。通过将两个最薄的矩形向右移动一个正方形然后向上移动,可以将其稍微提高到60 * 9 = 540,但是节省的空间很小,因此可能不值得任何额外的代码。
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
总面积为21895。
非高尔夫代码
f=->n{
a=(0..n*2).map{' '*40} #Fill an array with strings of 40 spaces
g=0 #Total height of all rectangles
m=n #Height of squarest rectangle (first guess is n)
(n**0.5).to_i.downto(1){|i|n%i<1&&(puts n/i #iterate through widths. Valid ones have n%i=0. Puts outputs heights for debugging.
m=[m,h=n/i].min #Calculate height of rectangle. On first calculation, m will be set to height of squarest rectangle.
g+=h+1 #Increment g
g<n+m+2? #if the rectangle will fit beneath the last one, against the left margin
(a[g-h-1,1]=(1..h).map{'*'*i+' '*40}) #fill the region of the array with stars
: #else
(x=(n+m-h..n+m).map{|j|r=a[j].rindex('* ');r ?r:-2}.max #find the first clear column
(n+m-h+1..n+m).each{|j|a[j][x+2]='*'*i} #and plot the rectangle along the bottom margin
)
)}
a} #return the array
puts f[gets.to_i]