9.1 KiB
Задача о максимальной вместимости
!!! question
Дан массив $ht$, каждый элемент которого представляет высоту вертикальной перегородки. Любые две перегородки в массиве и пространство между ними могут образовать контейнер.
Вместимость контейнера равна произведению высоты и ширины (площади), где высота определяется более короткой перегородкой, а ширина — разностью индексов двух перегородок в массиве.
Необходимо выбрать в массиве две перегородки так, чтобы вместимость образованного контейнера была максимальной, и вернуть максимальную вместимость. Пример показан на рисунке ниже.
Контейнер образован любыми двумя перегородками, поэтому состоянием в данной задаче являются индексы двух перегородок, обозначим их как $[i, j]$.
Согласно условию задачи, вместимость равна произведению высоты на ширину, где высота определяется короткой перегородкой, а ширина — разностью индексов двух перегородок в массиве. Обозначим вместимость как cap[i, j], тогда можно получить формулу для расчета:
cap[i, j] = \min(ht[i], ht[j]) \times (j - i)
Пусть длина массива равна n, количество комбинаций двух перегородок (общее число состояний) составляет C_n^2 = \frac{n(n - 1)}{2}. Наиболее прямой подход — перебрать все состояния, чтобы найти максимальную вместимость, временная сложность составит O(n^2).
Определение жадной стратегии
Для этой задачи существует более эффективное решение. Как показано на рисунке ниже, выберем состояние [i, j], которое удовлетворяет условию i < j и ht[i] < ht[j], то есть i — короткая перегородка, j — длинная перегородка.
Как показано на рисунке ниже, если сейчас переместить длинную перегородку j ближе к короткой перегородке i, вместимость обязательно уменьшится.
Это происходит потому, что после перемещения длинной перегородки j ширина j-i определенно уменьшится; а высота определяется короткой перегородкой, поэтому высота может только остаться неизменной (i остается короткой перегородкой) или уменьшиться (перемещенная j становится короткой перегородкой).
Рассуждая в обратном направлении, только сжимая короткую перегородку i внутрь, мы можем увеличить вместимость. Потому что хотя ширина определенно уменьшится, высота может увеличиться (перемещенная короткая перегородка i может стать длиннее). Например, на рисунке ниже после перемещения короткой перегородки площадь увеличивается.
Таким образом, можно вывести жадную стратегию для данной задачи: инициализировать два указателя по краям контейнера, на каждом шаге сжимать внутрь указатель, соответствующий короткой перегородке, пока два указателя не встретятся.
На рисунке ниже показан процесс выполнения жадной стратегии.
- В начальном состоянии указатели
iиjнаходятся на противоположных концах массива. - Вычислить вместимость текущего состояния
cap[i, j]и обновить максимальную вместимость. - Сравнить высоты перегородок
iиjи переместить короткую перегородку внутрь на одну позицию. - Циклически выполнять шаги
2.и3., покаiиjне встретятся.
Реализация кода
Код выполняет не более n итераций, поэтому временная сложность составляет $O(n)$.
Переменные i, j, res используют константное дополнительное пространство, поэтому пространственная сложность составляет $O(1)$.
[file]{max_capacity}-[class]{}-[func]{max_capacity}
Доказательство корректности
Причина, по которой жадный алгоритм быстрее полного перебора, заключается в том, что каждый жадный выбор «пропускает» некоторые состояния.
Например, в состоянии cap[i, j], где i — короткая перегородка, j — длинная перегородка. Если жадно переместить короткую перегородку i внутрь на одну позицию, это приведет к «пропуску» состояний, показанных на рисунке ниже. Это означает, что в дальнейшем невозможно будет проверить вместимость этих состояний.
cap[i, i+1], cap[i, i+2], \dots, cap[i, j-2], cap[i, j-1]
При наблюдении обнаруживается, что эти пропущенные состояния фактически являются всеми состояниями при перемещении длинной перегородки j внутрь. Ранее мы уже доказали, что перемещение длинной перегородки внутрь обязательно приводит к уменьшению вместимости. То есть пропущенные состояния не могут быть оптимальным решением, их пропуск не приведет к потере оптимального решения.
Приведенный выше анализ показывает, что операция перемещения короткой перегородки является «безопасной», жадная стратегия эффективна.













