루비, 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}
ungolfed 코드에서 몇 가지 변경. 가장 큰 것은 가장 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을 제외하고 위에서 언급 한 하한 내에서 필요한 테스트 사례에 대한 모든 사각형을 얻는 것이 실제로 가능합니다. 60은 다음 71 * 8 = 568 출력을 제공합니다. 가장 얇은 두 사각형을 한 정사각형으로 이동 한 다음 위쪽으로 이동하면 약간 60 * 9 = 540으로 약간 향상 될 수 있지만, 저장 비용은 최소화되므로 추가 코드를 사용할 가치가 없습니다.
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
총 면적은 21895입니다.
Ungolfed 코드
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]