(Я предполагаю, возможно, ошибочно, что ваши прямоугольники делятся на бесконечные, а не состоят из отдельных пикселей.)
Вы всегда можете получить точно правильные соотношения сторон, по какой-то цене в потраченных впустую прямоугольниках, приняв m = ceil (sqrt (n)) и используя m частей с каждой стороны.
В противном случае, вы ищете p, q близко к sqrt (n), так что pq> = n и p, q близки друг к другу. Лучший выбор p, q, конечно, будет зависеть от того, насколько вы готовы обменять отходы на неточность. Маловероятно, что вы когда-нибудь захотите взять p, q очень далеко от sqrt (n), потому что это даст вам большую ошибку в форме. Поэтому я думаю, что вы хотите что-то вроде этого:
p = ceiling(sqrt(n))
best_merit_yet = merit_function(p,p,0)
best_configuration_yet = (p,p)
for p from floor(sqrt(n)) downward:
# we need pq >= n and q as near to p as possible, which means (since p is too small) as small as possible
q = ceiling(n/p)
if max(merit_function(n/p,n/q,0), merit_function(n/q,n/p,0)) < best_merit_yet:
break
n_wasted = p*q-n
merit1 = merit_function(n/p,n/q,n_wasted)
merit2 = merit_function(n/q,n/p,n_wasted)
if max(merit1,merit2) > best_merit_yet:
if merit1 > merit2:
best_configuration_yet = (p,q)
best_merit_yet = merit1
else:
best_configuration_yet = (q,p)
best_merit_yet = merit2
и, надеюсь, тот факт, что очень неправильные фигуры очень плохие, будет означать, что вам никогда не придется делать много итераций цикла.
Здесь merit_function
должен воплощать ваши предпочтения в обмене формы на отходы.