Google Code Jam round 3
Я честно старался не пройти: долго писал 1-ю задачу, забыл поменять ограничения к large-тесту 2-й задачи, не заметил четвертую вершину у треугольника в графе 3-й задачи и забил на hard 4-й, но не получилось – занял 77 место, и, как следствие, попадаю в полуфинал. К сожалению, в деле «непопадания» в полуфинал преуспели остальные казахстанские участники, так что я, похоже, поеду один
Далее – немного о задачах (полные условия лежат здесь).
Задача A. How Big Are the Pockets?
В задаче требуется посчитать суммарную площадь «карманов» простого невыпуклого прямоугольного многоугольника. Точка считается лежащей в кармане, если она не лежит в многоугольнике и выше и ниже (или левее и правее) нее есть точки границы многоугольника. Гарантируется, что никакая координата никакой точки многоугольника не превышает по абсолютному значению 3000.
Решение
Для каждой целочисленной абсциссы x найдем y1 = min(y: (x,y) принадлежит многоугольнику) и y2 = min(y: (x,y) принадлежит многоугольнику). Аналогичное действие проделаем для ординат. Теперь посчитаем площадь Sa исходного многоугольника и Sb – площадь расширенного многоугольника. Расширенным будем считать исходный многоугольник с карманами. Sa считается методом трапеций, а Sb – перебором всех клеток 1×1 принадлежащих расширенному многоугольнику. Ответом к задаче будет Sb – Sa.
Задача B. Portal
Задача на лабиринт с портальной пушкой из Portal. Ходом считается только перемещение. Создание портала ходом не считается.
Решение
В качестве состояния будем использовать координаты 3-х клеток: наше местоположение, положение первого портала и положение второго портала (если подумать, то достаточно хранить всего лишь один портал, но с заданными ограничениями все работает и так). Если построить граф между этими состояниями, то можно заметить, что в нем будут только ребра весами 1 и 0. На таком графе задачу нахождения кратчайшего пути можно решить за линейное время обходом в ширину, используя следующий трюк: если производится переход по ребру весом 0 то вершину нужно добавлять не в конец очереди, а в начало. Самое простая реализация использует list или deque из STL.
Задача C. No Cheating
В задаче требуется найти максимальное количество учеников, которое можно посадить в классе так, чтобы они не списывали. Ученик может списывать, если у него есть сосед в показанных на рисунке направлениях.
Решение
Построим граф, используя направления списывания в качестве ребер. Задача сводится к нахождению наибольшего независимого множества вершин в этом графе. В общем виде задача NP-полная, однако если присмотреться, то можно заметить, что построенный граф двудольный. А для двудольного графа количество вершин в наибольшем независимом множестве равно N – K, где N – количество вершин в графе, а K – количество ребер в наибольшем паросочетании.
Задача D. Endless Knight
Нужно посчитать, сколькими способами можно добраться ходом коня из (1, 1) в (W, H), если ходить можно только так, что обе координаты увеличиваются, и есть запрещенные клетки.
Решение
Для маленьких ограничений задача решается обычной динамикой. Для больших, возможно, нужно использовать малые ограничения на количество запрещенных клеток и считать количества путей до каждой из них и между ними. UPD: Как отметил u1ik в своем комментарии: «Да, в четвертой задаче брутфорсная формула вкл./искл. Только надо еще научиться быстро считать С(n, m) для больших чисел по модулю.»
Да, в четвертой задаче брутфорсная формула вкл./искл. Только надо еще научиться быстро считать С(n, m) для больших чисел по модулю.
Интересно еще в какой офис гугла отправят. Оптимизация, видимо, будет по цене билета.