Изменения

Перейти к: навигация, поиск

Convex hull trick

30 байт добавлено, 14:23, 19 января 2017
Нет описания правки
'''for''' i = 2 = 1..n
dp[i] = <tex>+\infty</tex>
'''for''' j = 1..i-1
'''if''' (dp[j] + a[i] <tex>\cdot</tex> c[j] < dp[i])
dp[i] = dp[j] + a[i] <tex>\cdot</tex> c[j]
[[Файл:picture1convexhull.png]]
Выделим множество точек <tex>(x0x_0, y0y_0)</tex> , таких что все они принадлежат одной из прямых и при этом нету ни одной прямой <tex>y’(x)</tex>, такой что <tex>y’(x0x_0) < y0y_0</tex>. Иными словами возьмем «выпуклую (вверх) оболочку» нашего множества прямых (её еще называют нижней ошибающей множества прямых на плоскости). Назовем ее «<tex>y = convex(x)</tex>». Видно, что множество точек <math>(x, convex(x))</math> представляет собой выпуклую вверх функцию.
==Цель нижней огибающей множества прямых==
|proof=Достаточно показать, что последнюю прямую нужно удалить из множества <tex>\Leftrightarrow</tex>, когда она наша новая прямая пересекает ее в точке с координатой по оси X, меньшей, чем последняя - предпоследнюю.
Пусть <tex>Y(x) = Kx + B</tex> {{- --}} уравнение новой прямой, <tex>y[i](x) = K[i]x + B[i]</tex> - уравнения прямых множества. Тогда т.к. <tex>K < K[sz]</tex>, то при <tex>x \in [- \infty; xR] : y[sz](x) <= Y(x)</tex>, а т.к. <tex> K[sz] < K[sz - 1]</tex>, то при <tex>x \in [xL; + \infty] : y[sz - 1](x) \geqslant y[sz](x)</tex>. Если <tex>xL < xR</tex>, то при <tex>x \in [xL; xR] : y[sz - 1] \geqslant y[sz](x) и Y(x) \geqslant y[sz](x)</tex>, т.е. на отрезке <tex>[xL; xR]</tex> прямая номер sz лежит ниже остальных и её нужно оставить в множестве. Если же <tex>xL > xR</tex>, то она ниже всех на отрезке <tex>[xL; xR] = \varnothing </tex>, т.е. её можно удалить из множества.
}}
sz = sz + 1
'''return''' dp[n]
Здесь функция <tex>\mathtt{divide(a, b)}</tex> возвращает нужное(*) округление <tex>\frac{a / b}</tex>. Приведем её код :
'''int''' <tex>\mathtt{divide}</tex>('''int''' a, '''int''' b)
delta = 0
186
правок

Навигация