задачка (программирование)
May. 25th, 2014 06:08 pmМне эта задачка попалась недавно на сайте программистских соревнований, когда я помогал кое-кому готовиться к интервью и искал материал для интересных вопросов. Она мне понравилась тем, что я не смог ее быстро решить.
Комментарии я скрывать не буду - если хотите предложить там свое решение, то пожалуйста, если хотите подумать сами, не заглядывайте туда.
P.S. Я бы сказал, опираясь на собственный опыт, что эта задача несколько сложнее, чем типичная алгоритмическая задача на интервью в Гугле. Если вы можете эту задачу решить и за 45 минут написать работающий код, за разумное время дающий правильный ответ - ваш уровень по крайней мере в алгоритмах вполне подходит и даже превосходит то, что в Гугле просят продемонстрировать на интервью.
Вы - авиадиспетчер, которому нужно посадить N самолетов в аэропорту, у которого только одна посадочная полоса. Про каждый самолет известно окно времени, в которое он может безопасно приземлиться - оно задается в минутах, от 0 до 1440. Например, про один самолет может быть известно, что его можно посадить в любое время от 7-й минуты до 300-й включительно, про другой - в любое время от 100-й до 200-й, и так далее. Предположим, что вы для каждого самолета выбрали время посадки (его можно задать с точностью до секунды). Будет какое-то минимальное временное расстояние между посадками самолетов. Ваша задача -- это минимальное расстояние максимизировать.
На вход вам дается: число самолетов N, от 2 до 8; для каждого самолета начальная и конечная границы окна, от 0 до 1440. На выход вы должны дать: максимальное значение минимального расстояния между посадками, которое вы беретесь обеспечить.
Комментарии я скрывать не буду - если хотите предложить там свое решение, то пожалуйста, если хотите подумать сами, не заглядывайте туда.
P.S. Я бы сказал, опираясь на собственный опыт, что эта задача несколько сложнее, чем типичная алгоритмическая задача на интервью в Гугле. Если вы можете эту задачу решить и за 45 минут написать работающий код, за разумное время дающий правильный ответ - ваш уровень по крайней мере в алгоритмах вполне подходит и даже превосходит то, что в Гугле просят продемонстрировать на интервью.
no subject
Date: 2014-05-25 03:22 pm (UTC)no subject
Date: 2014-05-25 08:37 pm (UTC)no subject
Date: 2014-05-25 03:30 pm (UTC)no subject
Date: 2014-05-25 03:41 pm (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 03:35 pm (UTC)Вход: (N окон, Start time, End Time)
Для всех самолетов А из N
- выбрать А первым самолетом в расписании посадок
- Назначить ему время посадки T_A - самое раннее из возможных
- Найти такое T', что
(Уравнение 1): (T'-T_A) = FindMaxMinGap(N-1 оставшихся окон, T', End Time)
(если такого нет, то наибольшее T', для которого левая часть меньше правой)
- вернуть (T'-T_A)
Если N=1, вернуть T_E - Start_time, где T_E = самое позднее время посадки данного самолета.
Ключевой момент - поиск T'. Здесь мы замечаем, что FindMaxMinGap - невозрастающая функция от второго параметра (Start Time), поэтому решение уравнения (1) можно провести бинарным поиском - т.е. порядка 16 попыток для 86400 возможных позиций. Итого сложность будет где-то 16^N * (N!).
no subject
Date: 2014-05-25 03:48 pm (UTC)первый самолет посадить в минимальную границу, последний - в максимальную.
Остальные самолеты первоначально расположить произвольно. Затем рассчитать попарные расстояния между соседними. понятно, что расстояния между не-соседними можно не принимать во внимание. после этого начать усреднять эти расстояния. В качестве начальной пары можно взять минимальное и усреднить с бОльшим из соседей. Далее цикл повторяется. Если новое значение оказывается за пределами окна для данного самолета - оставить на ближайшей к этому значению границе.
Поннятно, что при таком алгоритме минимальное расстояние не уменьшается, и ограницено сверху значением 1440/(N-1), поэтому имеет предел. Установить порог изменения в 1 секунду, после чего цикл обрывать при изменениях меньше секунды.
Насчет скорости сходимости алгоритма - надо подумать, сходу кажется, что количество операций - полином от N.
no subject
Date: 2014-05-25 03:58 pm (UTC)(no subject)
From:no subject
Date: 2014-05-25 03:49 pm (UTC)Делением пополам перебираем размеры минимального расстояния (log(1440/(N-1)).
Пытаемся расставить самолеты с заданным минимальным расстоянием и в заданном порядке (легко сделать за один проход).
Итого: O(N*N!*log(1440/(N-1))) - при ограничении на N <= 8 должно давать разумное время.
no subject
Date: 2014-05-25 07:05 pm (UTC)(no subject)
From:no subject
Date: 2014-05-25 03:53 pm (UTC)no subject
Date: 2014-05-25 04:30 pm (UTC)no subject
Date: 2014-05-25 04:33 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 05:18 pm (UTC)Но вот что с перестановками делать - ума не приложу.
no subject
Date: 2014-05-25 05:20 pm (UTC)no subject
Date: 2014-05-25 05:34 pm (UTC)должно сработать. конечно, при таком алгоритме порядок посадки самолетов не изменится, так что на глобальный оптимум не надеемся. но можно попробовать несколько раз с первыми случайными распределениями (т.е. с разной очередностью).
no subject
Date: 2014-05-25 07:00 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 05:38 pm (UTC)no subject
Date: 2014-05-27 08:43 am (UTC)Почему ? Как ?
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 05:55 pm (UTC)no subject
Date: 2014-05-25 06:39 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 06:30 pm (UTC)Ставим все времена на левые края окон.
Берем 1 самолет и двигаем его по его интервалу - если какое то новое положение 1го самолета дает общий выигрыш, то оставляем его.
Берем 2 самолет и двигаем ...
...
Берем N самолет и двигаем...
И снова берем 1 самолет ...
Продолжать, пока не получим, что ни один из N самолетов нельзя переставить не ухудшив результат.
no subject
Date: 2014-05-25 06:41 pm (UTC)no subject
Date: 2014-05-25 07:04 pm (UTC)no subject
Date: 2014-05-25 06:54 pm (UTC)- Ищем min левых границ и max правых, этот диапазон разбиваем на равные N-1 частей - получаем "идеальные" точки
- Смотрим, диапазоны, не покрывающие ни одной, ищем среди них минимальное расстояние от границы диапазона до одной из точек, сдвигаем её на границу диапазона, отрезки по обе стороны переразбиваем, диапазон и точку убираем из рассмотрения
- Смотрим точки, не покрытые ни одним диапазоном, та же процедура
- Все диапазоны покрывают хотя бы одну точку и каждая покрыта хотя бы одним диапазоном - можно распределить без дальнейших сдвигов времени вылетов - не будем этого делать, просто смотрим минимум, это результат
В каком случае такой подход ломается?
no subject
Date: 2014-05-26 08:57 pm (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 08:30 pm (UTC)Будем рассматривать частичные последовательности, хранить их в приоритетной очереди и расширять, начиная с текущуей отимальной.
Начнём с (1,2) и (2,1), где цифры - номера самолётов. Пусть в первой интервал меньше, тогра по ней строим (3,1,2), (1,3,2), (1,2,3).
Невозможные выкидываем, медлыенные ставим на нужное место в очереди. Возможно, в оценке медленности стот добавить длинну последовательности.
Ещё пара эвристик - заранее выкинуть невозможные двойки и тройки, на случайных данных они должны хорошо сократить количество вариантов.
PS. Хочу узнать правильный ответ ))
no subject
Date: 2014-05-25 08:36 pm (UTC)no subject
Date: 2014-05-25 08:56 pm (UTC)no subject
Date: 2014-05-25 09:07 pm (UTC)Во-первых, никаких симплекс-методов и т.д. такие задачки не подразумевают. Даже думать в эту сторону не надо.
Во-вторых, ограничение на N от 2 до 8 нам явно говорит о том, что ожидаемое решение подразумевает перебор N! А иначе, почему N такое маленькое ?
И в-третьих, вот это mim max условие максимальное значение минимального расстояния очень напоминает пример FairWorkload отсюда (http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binarySearch)
no subject
Date: 2014-05-26 08:55 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2014-05-25 09:42 pm (UTC)no subject
Date: 2014-05-25 11:06 pm (UTC)Перебираем N! перестановок самолётов (для N=8 это вполне обозримое количество - 40320 гипотез) задающих очерёдность захода на посадку.
Каждый самолёт сажаем как можно раньше, - разумеется, строго после предыдущего.
Находим минимальное время.
no subject
Date: 2014-05-26 09:01 am (UTC)no subject
Date: 2014-05-26 01:18 am (UTC)Еще я не заметил, что самолетов "до 8" - это сразу сводит задачу к "все пермутации и больше ни о чем не думай".
Как решавший эту задачу на практике - выстраивание очереди кораблей к причалу - практически те же условия, как и у самолетов, добавлю, что на практике такое решение не очень годится, если очередь из 20-30.
no subject
Date: 2014-05-26 09:02 am (UTC)Тогда, конечно, все перестановки и пошло оно нах.
no subject
Date: 2014-05-26 09:00 am (UTC)no subject
Date: 2014-05-26 06:28 pm (UTC)no subject
Date: 2014-05-27 03:24 am (UTC)звучит как требование сделать одно расстояние максимально большим, но не оптимизировать весь набор
ставим всех на начало интервала, последнего на конец интервала и затем двигаем в минимальной паре тот самолет на секунду наружу, чей третий сосед дальше. для малых Н должно сработать за разумное время
no subject
Date: 2014-05-27 03:32 am (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2014-06-29 09:57 pm (UTC)В худшем случае исходную задачу быстрее решить не удастся, но если интервалы случайно распределены, то или оптимальное время на какой-нибудь перестановке получим или самих перестановок будет существенно меньше, чем N!
no subject
Date: 2014-09-03 04:41 pm (UTC)https://github.com/Alexander-Panin/planes/blob/master/my.py