Ruby, 228 byte * 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ột số thay đổi từ mã không mã hóa. Lớn nhất là thay đổi ý nghĩa của biến m
từ chiều cao của hình chữ nhật vuông, đến chiều cao của hình chữ nhật vuông cộng n
.
Một cách tầm thường, *40
đã được thay đổi thành *n
có nghĩa là rất nhiều khoảng trắng không cần thiết ở bên phải cho lớn n
; và -2
được thay đổi thành 0
có nghĩa là hình chữ nhật được vẽ trên đáy luôn bỏ lỡ hai cột đầu tiên (điều này dẫn đến việc đóng gói kém hơn cho các số có chỉ số nhân (n/2)*2
)
Giải trình
Cuối cùng tôi đã tìm thấy thời gian để trở lại điều này.
Đối với một n
trường nhỏ nhất định phải có đủ không gian cho cả hình chữ nhật dài nhất 1*n
và hình chữ nhật vuông x*y
. Rõ ràng là có thể đạt được bố cục tốt nhất nếu cả hai hình chữ nhật có các cạnh dài được định hướng theo cùng một hướng.
Bỏ qua yêu cầu về khoảng trắng giữa các hình chữ nhật, chúng tôi thấy rằng tổng diện tích là (n+y)*x = (n+n/x)*x
hoặc n*(x+1)
. Dù bằng cách nào, điều này đánh giá n*x + n
. Bao gồm cả khoảng trắng, chúng ta phải thêm một phần phụ x
nếu chúng ta đặt các hình chữ nhật từ đầu đến cuối hoặc n
nếu chúng ta đặt các hình chữ nhật cạnh nhau. Do đó, trước đây là thích hợp hơn.
Điều này đưa ra các mức dưới đây (n+y+1)*x
cho khu vực trường:
n area
60 71*6=426
111 149*3=447
230 254*10=2540
400 421*20=8240
480 505*20=10100
Điều này cho thấy thuật toán sau:
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.)
Thực tế có thể lấy tất cả các hình chữ nhật cho các trường hợp thử nghiệm được yêu cầu trong các giới hạn dưới đã đề cập ở trên, ngoại trừ 60, cho ra đầu ra 71 * 8 = 568 sau đây. Điều này có thể được cải thiện một chút thành 60 * 9 = 540 bằng cách di chuyển hai hình chữ nhật mỏng nhất bên phải một hình vuông rồi lên, nhưng việc tiết kiệm là tối thiểu, do đó có lẽ không đáng để thêm bất kỳ mã nào.
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
Điều này cho tổng diện tích 21895.
Mã bị đánh cắp
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]