Rubinowy, 228 bajtów * 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}
Kilka zmian w stosunku do niepoznanego kodu. Największa jest zmiana znaczenia zmiennej mz wysokości prostokąta kwadratowego na wysokość prostokąta kwadratowego plus n.
Trywialnie *40został zmieniony na, *nco oznacza wiele niepotrzebnych białych znaków po prawej stronie dla dużych n; i -2zmienia się na, 0co oznacza, że prostokąty narysowane wzdłuż dna zawsze pomijają dwie pierwsze kolumny (powoduje to gorsze upakowanie liczb, których jedynym rozkładem jest faktoryzacja (n/2)*2)
Wyjaśnienie
W końcu znalazłem czas, aby wrócić do tego.
Dla danego npola najmniejsze pole musi mieć wystarczająco dużo miejsca zarówno dla najdłuższego prostokąta, jak 1*ni kwadratu prostokąta x*y. Powinno być oczywiste, że najlepszy układ można osiągnąć, jeśli oba prostokąty mają długie boki ustawione w tym samym kierunku.
Nie zwracając uwagi na wymóg spacji między prostokątami, okazuje się, że całkowita powierzchnia jest albo (n+y)*x = (n+n/x)*xalbo n*(x+1). Tak czy inaczej, to ocenia n*x + n. Uwzględniając spację, musimy dodać dodatkowy, xjeśli umieszczamy prostokąty od końca do końca lub njeśli umieszczamy prostokąty obok siebie. Ten pierwszy jest zatem preferowany.
Daje to następujące dolne granice (n+y+1)*xobszaru pola:
n area
60 71*6=426
111 149*3=447
230 254*10=2540
400 421*20=8240
480 505*20=10100
Sugeruje to następujący algorytm:
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.)
Możliwe jest uzyskanie wszystkich prostokątów dla wymaganych przypadków testowych w wyżej wymienionych dolnych granicach, z wyjątkiem 60, co daje następującą wartość wyjściową 71 * 8 = 568. Można to nieco poprawić do 60 * 9 = 540, przesuwając dwa najcieńsze prostokąty o jeden kwadrat w prawo, a następnie w górę, ale oszczędność jest minimalna, więc prawdopodobnie nie jest wart żadnego dodatkowego kodu.
10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
***** *
*
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
**** *
*
*** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
** *
To daje łączną powierzchnię 21895.
Nieskluczony kod
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]