задача
Вам будет дан набор окружностей на плоскости с центрами на прямой y = 0 . Гарантируется, что ни одна пара окружностей не имеет более одной общей точки.
Ваша задача - определить, на сколько областей плоскости делят круги. Область - это максимальное непрерывное множество точек включения, не пересекающих ни одну из окружностей.
Вы должны написать программу, которая вычисляет этот ответ, когда дано описание кругов.
Вот пример:
С левой стороны вы видите круги, нарисованные в плоскости. Тем не менее, в правой половине изображения области, созданные кругами, окрашены отчетливо (по одному цвету на область). В этом примере шесть регионов.
вход
Первая строка ввода содержит число, N
количество описаний кругов, которым необходимо следовать. Эта строка необязательна, если ваше решение работает без нее, это нормально.
N
Каждая из следующих строк содержит два целых числа x i и r i > 0 , представляющих окружность с центром (x i , 0) и радиусом r i .
Гарантируется, что ни одна пара окружностей не имеет более одной общей точки. Кроме того, гарантируется, что x i и r i не превышают 10^9
по абсолютной величине (поэтому они удобно вписываются в 32-разрядное целое число).
Вход может быть:
читать из STDIN
читать из файла с именем
I
в текущем каталоге
В качестве альтернативы вход может быть:
доступный как строка (включая переводы строки) в глобальной переменной
в стеке
Выход
Это должно быть одно целое число, количество произведенных регионов. Это должно быть записано в STDOUT или файл с именем O
в текущем каталоге.
правила
Самый короткий код в байтах выигрывает
+ 200 байт, если ваш код не имеет полинома времени выполнения + сложность пространства в
n
Бонус -100 байт для наихудшего ожидаемого времени выполнения + сложность пространства
O(n log n)
Бонус -50 байт для наихудшего ожидаемого времени выполнения + сложность пространства
O(n)
Бонус -100 байт для детерминированной среды выполнения + сложность пространства
O(n)
При оценке времени выполнения:
Предположим, что у хеш-таблиц
O(1)
ожидаемое время выполнения для вставки, удаления и поиска независимо от последовательности операций и входных данных. Это может или не может быть правдой, в зависимости от того, использует ли реализация рандомизацию.Предположим, что встроенная сортировка вашего языка программирования занимает детерминированное
O(n log n)
время, гдеn
размер входной последовательности.Предположим, что арифметические операции над входными числами занимают только
O(1)
время.Не предполагайте, что входные числа связаны константой, хотя, по практическим причинам, они есть. Это означает, что алгоритмы, такие как сортировка по основанию или сортировка по счету, не являются линейным временем. В общем, следует избегать очень больших постоянных факторов.
Примеры
Входные данные:
2
1 3
5 1
Выход: 3
Входные данные:
3
2 2
1 1
3 1
Выход: 5
4
7 5
-9 11
11 9
0 20
Входные данные:
9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2
Выход: 11
Советы
Мы можем использовать следующую идею для очень компактного решения. Давайте пересечем набор окружностей с осью X и интерпретируем точки пересечения как узлы на плоском графе:
Каждый круг создает в этом графе ровно 2 ребра и до двух узлов. Мы можем подсчитать количество узлов, используя хеш-таблицу, чтобы отслеживать общее количество различных левых или правых границ.
Тогда мы можем использовать характеристическую формулу Эйлера для вычисления количества граней чертежа графа:
V - E + F - C = 1
F = E - V + C + 1
Чтобы вычислить C
количество подключенных компонентов, мы можем использовать поиск в глубину .
Примечание. Эта проблемная идея заимствована из недавнего конкурса хорватских программистов , но, пожалуйста, не читайте, читая обзор решения. :)
n log n
бонус? Также у меня есть новое концептуально новое решение. Должен ли я опубликовать новый ответ или заменить старый? (Я бы предпочел первое, если мое новое решение на самом деле не верное)Ответы:
Mathematica,
125122 - 150 = -28 символовЯ не знаю сложности встроенной функции
ConnectedComponents
.Использование:
источник
ConnectedComponents
имеет линейную ожидаемую сложность наихудшего случая, поэтому, если есть O (n) компонентов, это было бы хорошо. Я не понимаю Mathematica, поэтому я не могу сказать, является ли это O (n) в целом и соответствует ли он бонусу -150? Я думаю, что это так. Я просто запускаю его с вводом в STDIN?Рубин -
312306285273269259 символовЭтот ответ был заменен моим другим подходом, который использует значительно меньше символов и работает
O(n log n)
.Хорошо, идем. Для начала, я просто хотел рабочую реализацию, так что это еще не оптимизировано алгоритмически. Я сортирую круги от самых больших до самых маленьких и строю дерево (круги, включенные в другие круги, являются потомками этих более крупных). Обе операции идут
O(n^2)
в худшем иO(n log n)
в лучшем случае. Затем я перебираю дерево для подсчета площадей. Если дочерние элементы круга заполняют весь его диаметр, появляются две новые области, в противном случае - только одна. Эту итерацию возьмитеO(n)
. Так что у меня общая сложностьO(n^2)
и я не могу претендовать ни на награду, ни на штраф.Этот код ожидает, что ввод без количества кружков будет сохранен в переменной
s
:Неуправляемая версия (ожидается ввод в переменной
string
):источник
11
. За тот, что в вашем комментарии9
.10
и8
с моей версией без гольфа, но11
и9
с моей текущей версией игры в гольф: DРубин,
203183173133 - 100 = 33 символаТак что здесь другой подход. На этот раз я сортирую круги по их самой левой точке. Круги, соприкасающиеся в самой левой точке, сортируются от наибольшего к наименьшему. Это требует
O(n log n)
(ну, Ruby использует быструю сортировку, так что на самом делеO(n^2)
реализация сортировки слиянием / кучей, вероятно, выходит за рамки этой задачи). Затем я перебираю этот список, помня все крайние левые и крайние правые позиции кругов, которые я посетил. Это позволяет мне определить, соединяется ли серия кругов по всему большему кругу. В этом случае есть два подрайона, иначе только один. Эта итерация требует толькоO(n)
полной сложности,O(n log n)
которая дает право на вознаграждение в 100 символов.Этот фрагмент ожидает, что входные данные будут предоставлены через файл в аргументах командной строки без количества кружков:
Версия без поддержки (ожидает ввода в переменную
string
):источник
-1 1 1 1 0 2 4 2 0 6
. Я подумаю, как это исправить к завтрашнему вечеру (надеюсь).Юля - 260 -100 (бонус?) = 160
ОБНОВЛЕНИЕ: Подумав некоторое время, я понял, что проблема с моим методом была только тогда, когда круги не связаны, поэтому у меня возникла идея, почему бы не соединить их искусственно? Таким образом, все будет удовлетворять формуле Эйлера.
F = 2 + EV (V = 6, E = 9)
[Не работать с вложенными кругами, так что это не является решением проблемы для общих случаев]
Код :
источник
2 -10 1 10 1
.n=2
Круги(C=(-10,0), r=1)
а(C=(10,0), r=1)
4 0 2 1 1 10 2 11 1
но я не думаю, что могу дать вам намного больше тестовых случаев, это было бы немного несправедливоSpidermonkey JS,
308, 287, 273 - 100 = 173Я думаю, если бы я переписал это на Ruby или Python, я мог бы сохранить символы.
Код:
Алгоритм:
Я не очень хорош в больших обозначениях O, но я думаю, что это O (n), так как я эффективно перебираю каждый круг 3 раза (создать, слева, справа), а также сортирую ключи карты (и я сортирую по O ( п лог п) но это исчезает). Это детерминированный?
источник
r
цикл иl
цикл в одно утверждение, я был бы признателен.JavaScript (ES6) -
255254 символов -100250 Бонус =1554Предполагается, что входная строка находится в переменной
S
и выводит количество регионов на консоль.Временная сложность теперь O (N).
Тестовый пример 1
Выходы:
3
Тестовый пример 2
Выходы:
5
Тестовый пример 3
Выходы:
6
Тестовый пример 4
Выходы:
11
Тестовый пример 5
Выходы:
105
Предыдущая версия
С комментариями:
Общая сложность по времени составляет O (N) для всего, кроме сортировки, которая является O (N.log (N)) - однако, если заменить ее на сортировку по сегментам, это уменьшит общую сложность до O (N).
Требуемая память O (N).
Угадайте, что будет дальше в моем списке задач ... сортировка ведра менее чем в 150 символах.Выполненоисточник
O(n)
(на самом делеO(n+k)
), ноO(n^2)
илиO(n log n)
худший случай, в зависимости от алгоритма сортировки, используемого внутри сегментов, поэтому вам нужно сделать это в 50 символов.