litbaza книги онлайнРазная литератураГрокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих - Адитья Бхаргава

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 27 28 29 30 31 32 33 34 35 ... 46
Перейти на страницу:
первым городом в маршруте.

Однако в каких-то ситуациях начальный город не задан. Допустим, вы работаете в курьерской службе FedEx и должны доставить пакет в пределах города. Пакет перевозится из Чикаго в один из 50 филиалов FedEx. Затем пакет будет перегружен в машину, которая разъезжает по разным местам и доставляет пакеты. В какой филиал отгрузить пакет? На этот раз начальная точка неизвестна, и в задаче о коммивояжере вам придется вычислить как оптимальный путь, так и начальную точку.

Время выполнения обеих версий одинаково. Однако отсутствие определенного начального города упрощает пример, поэтому я выберу эту версию.

Два города = два возможных маршрута.

Сколько маршрутов?

На первый взгляд может показаться, что это один маршрут. Разве расстояние СФ>Марин не совпадает с расстоянием Марин>СФ? Не всегда. В некоторых городах (в том числе и в Сан-Франциско) много улиц с односторонним движением, и тогда вам не удается вернуться по тому пути, по которому вы приехали. Иногда приходится проехать лишнюю пару миль, чтобы найти выезд на шоссе. Так что эти два маршрута не всегда совпадают.

Три города

Теперь добавим к двум городам еще один. Сколько возможных маршрутов существует в этой конфигурации?

Если начать в Беркли, вы можете посетить два города.

Всего шесть возможных маршрутов: по два для каждого города, с которого вы можете начать.

Итак, три города = шесть возможных маршрутов.

Четыре города

Добавим еще один город — Фремонт. Теперь допустим, что вы начали с Фремонта.

Мы знаем, что во Фремонте начинаются шесть возможных маршрутов. Ого! Да они очень похожи на шесть маршрутов, которые вы вычислили ранее, когда городов было всего три! Только теперь во всех маршрутах появился дополнительный город, Фремонт! Начинает проявляться закономерность. Предположим, из четырех городов выбирается начальный город Фремонт. Остается еще три города. И вы знаете, что для перемещения между тремя городами есть шесть разных маршрутов. Итак, если начать с Фремонта, существуют шесть возможных маршрутов. Также возможно начать с одного из других городов.

Четыре возможных начальных города, шесть возможных маршрутов для каждого начального города = 4 × 6 = 24 возможных маршрута.

Замечаете закономерность? Каждый раз, когда вы добавляете новый город, увеличивается количество вычисляемых маршрутов.

Сколько возможных маршрутов существует для шести городов? 720, говорите? Да, вы правы. 5040 для 7 городов, 40 320 для 8 городов.

Такая зависимость называется факториальной (помните, что об этом говорилось в главе 3?) Итак, 5! = 120. Допустим, есть 10 городов. Сколько существует возможных маршрутов? 10! = 3 628 800. Уже для 10 городов приходится вычислять более 3 миллионов возможных маршрутов. Как видите, количество возможных маршрутов стремительно растет! Вот почему невозможно вычислить «правильное» решение задачи о коммивояжере при очень большом количестве городов.

У задачи о коммивояжере и задаче покрытия множества есть кое-что общее: вы вычисляете каждое возможное решение и выбираете кратчайшее/минимальное. Обе эти задачи являются NP-полными.

Приближенное решение

Как выглядит хороший приближенный алгоритм для задачи о коммивояжере? Это должен быть простой алгоритм, находящий короткий путь. Попробуйте самостоятельно найти ответ, прежде чем продолжить чтение.

Я бы сделал это примерно так: начальный город выбирается произвольно, после чего каждый раз, когда коммивояжер выбирает следующий город, он перемещается в ближайший город из тех, что он еще не посещал. Допустим, он начинает в Марине.

Суммарное расстояние — 71 миля. Может, это не самый короткий путь, но он достаточно близок к нему.

Короткое объяснение NP-полноты: некоторые задачи прославились сложностью своего решения. Задача о коммивояжере и задача о покрытии множества — два классических примера. Многие эксперты считают, что написать быстрый алгоритм для решения таких задач невозможно.

Как определить, что задача является NP-полной?

Джон подбирает игроков для своей команды по американскому футболу. У него есть список нужных качеств: хорошо играет в нападении, хорошо играет в защите, хорошо играет под дождем, хорошо играет под давлением и т.д. Также имеется список игроков, в котором каждый игрок обладает определенными качествами.

Джон хочет подобрать команду, которая обладает полным набором качеств, но размер команды ограничен. «Минутку, — осознает Джон, — но ведь это задача покрытия множества!»

Для создания команды Джон может воспользоваться тем же приближенным алгоритмом:

1. Найти игрока с большинством качеств, которые еще не были реализованы.

2. Повторять до тех пор, пока не будут реализованы все качества (или пока не кончатся свободные места в команде).

NP-полные задачи встречаются очень часто. И было бы полезно, если бы вы могли понять, что решаемая задача является NP-полной. В этот момент можно прекратить поиски идеального решения и перейти к решению с применением приближенного алгоритма. Но определить, является ли ваша задача NP-полной, непросто. Обычно различия между легко решаемыми и NP-полными задачами весьма незначительны. Например, в предыдущих главах я много говорил о кратчайших путях. Вы знаете, как вычислить кратчайший путь из точки A в точку B.

Но если вы хотите найти кратчайший путь, соединяющий несколько точек, то это уже задача о коммивояжере, которая является NP-полной. Короче говоря, не существует простого способа определить, является ли задача, с которой вы работаете, NP-полной. Несколько характерных признаков:

• ваш алгоритм быстро работает при малом количестве элементов, но сильно замедляется при увеличении их числа;

• формулировка «все комбинации X» часто указывает на NP-полноту задачи;

• вам приходится вычислять все возможные варианты X, потому что задачу невозможно разбить на меньшие подзадачи? Такая задача

1 ... 27 28 29 30 31 32 33 34 35 ... 46
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?