У вас есть объективная функция : getBoxVolume()
.Ваша цель состоит в том, чтобы максимизировать значение этой функции.
В настоящее время вы максимизируете ее, используя что-то эквивалентное выборка : вы проверяете каждые STEP_SIZE
, чтобы увидеть, получите ли вы лучший результат.Вы определили основную проблему: нет гарантии, что граница интервала STEP_SIZE
находится где-нибудь вблизи максимального значения.
Обратите внимание на что-то в вашей целевой функции: она выпуклая.То есть он начинает расти (когда h = 0
, объем равен нулю, затем растет, как h
), достигает максимума, затем падает, в конце концов достигает нуля (когда h = min(l,w)/2
).
Это означает, что максимальное значение one гарантировано, и вам просто нужно его найти.Это делает эту проблему отличным случаем для бинарного поиска , потому что, учитывая характер функции, вы можете выбрать две точки функции и узнать, в каком направлении лежит максимум относительно этих двухточки.Вы можете использовать это с тремя точками за раз (слева, справа, посередине), чтобы выяснить, находится ли максимум между левым и средним, или средним и правым.Как только эти значения приблизятся друг к другу (они находятся в некотором фиксированном количестве e
друг от друга), вы можете вернуть значение функции там.Вы даже можете доказать, что возвращаемое вами значение находится в пределах некоторого значения e'
от максимального возможного значения.
Вот псевдокод:
max(double lowerEnd, upperEnd) {
double midPoint = (upperEnd + lowerEnd) / 2
double midValue = getBoxVolume(l, w, midpoint)
double slope = (getBoxVolume(l, w, midpoint + epsilon) - midValue) / epsilon
if (Math.abs(slope) < epsilon2) { // or, if you choose, if (upperEnd - lowerEnd < epsilon3)
return midpoint
}
if (slope < 0) { // we're on the downslope
return max(lowerEnd, midPoint)
}
else { // we're on the up-slope
return max(midpoint, upperEnd)
}
}