Блог пользователя e-maxx

Автор e-maxx, 13 лет назад, По-русски


Самый важный шаг на пути к решению этой задачи - понять, что достаточно рассматривать только такие повороты пылесоса, когда одна из его сторон полностью прижата к стороне комнаты.


Чтобы понять это, можно рассуждать таким образом. Пусть наше утверждение неверно, т.е. есть оптимальное положение пылесоса, когда ни к одной, ни к другой стороне комнаты многоугольник не прижат. Обозначим через i и j номера вершин, которыми этот многоугольник касается сторон комнаты. Понятно, что форма самого многоугольника между вершинами i и j ни на что не влияет: при любом повороте от площади треугольника OP[i]P[j] отнимается какая-то константная площадь, определяемая формой этого многоугольника (на рисунке она обозначена голубой заливкой).

Значит, сама форма ни на что не влияет, а мы должны просто минимизировать площадь прямоугольного треугольника OP[i]P[j], но учитывая, что гипотенуза имеет фиксированную длину, становится понятно, что минимум достигается в граничных случаях: когда мы максимально прижимаем гипотенузу к одной из сторон комнаты.

Итак, утверждение доказано, теперь надо понять, как написать быстрое решение. У нас уже есть решение за квадрат: перебирать сторону с точкой i, прикладывать её к каждой из сторон комнаты, искать крайнюю точку j и считать получающуюся в углу площадь. Чтобы написать быстрое решение, надо научиться обе этих вещи делать за константное время: искать точку j и считать ответ.

Точку j поддерживать легко: мы можем просто перебирать прижимаемую сторону i в порядке обхода многоугольника, тогда крайнюю точку j мы можем просто поддерживать по методу движущегося указателя (т.е. при переходе к следующему i продвигать и указатель j вперёд, пока он не достигнет нужной крайней точки).

Несколько сложнее ситуация с подсчётом ответа. Чтобы вычислять его быстро, надо, согласно рисунку, быстро уметь считать площадь такой области между любыми двумя точками i и j. Для этого, например, найдём центр масс Q многоугольника и предпосчитаем все частичные суммы S[i] - суммы треугольников QP[j - 1]P[j] по всем j ≤ i. После такого предпосчёта ответ получается как комбинация разности двух значений массива S[] и площадей треугольников QP[i]P[j] и OP[i]P[j].
Разбор задач Codeforces Beta Round 50
  • Проголосовать: нравится
  • +19
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Удивлён, что так плохо порешали её. Надеюсь, у нас палева нет :)
13 лет назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится
Можно было считать по другому площадь таких частей.
фактически у нас точки p[i], p[i + 1], ... p[j], O и надо посчитать площать многоугольника)
Получается такая формула: S = abs(p[i] * p[i + 1] + p[i + 1] * p[i + 2] + ... p[j - 1] * p[j] + p[j] * O + O * p[i]) * 0.5
где a * b = a.x * b.y - a.y * b.x - что-то типа векторного произведения :)
p[i] * p[i + 1] + p[i + 1] * p[i + 2] + ... p[j - 1] * p[j]  - такую сумму надо быстро посчитать.
s[0] = p[n - 1] * p[0]
s[i] = s[i - 1] + p[i - 1] * p[i];
p[i] * p[i + 1] + p[i + 1] * p[i + 2] + ... p[j - 1] * p[j] = s[j] - s[i], если i <= j
p[i] * p[i + 1] + p[i + 1] * p[i + 2] + ... p[j - 1] * p[j] = s[n - 1] - s[i] + s[j], если i > j
По-моему это немного проще :)

  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Ну да, чуть проще, и к тому же не нужен дабловый центр масс.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Видимо, не все осознали, что сторону многоугольника надо прижимать к стороне угла, поэтому и так плохо сдавалось. Некоторые (например, winger) писали троичный поиск по тому, как при данных опорных точках расположить прямой угол.

Вообще, хорошая простая задача на технику вращающихся калиперов. И решение получается коротким, особенно если считать площади правильно. А самый простой подсчет площадей даже не использует частичных сумм наподобие того, что изложил pperm - достаточно один раз подсчитать площадь в лоб (две компоненты - "отрезок" многоугольника и два катета от треугольника), а затем обновлять первую составляющую инкрементально за O(1).