Как реализовать TSP с динамикой в ​​C++

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

Мне посоветовали использовать Dijkstra с приоритетной очередью, чтобы создать матрицу связности для 15 городов, которые мне нужно посетить, а затем выполнить TSP для этой матрицы с помощью DP. Раньше я использовал только Дейкстру с O (n ^ 2). После попыток выяснить, как реализовать Дейкстру, я, наконец, сделал это (достаточно, чтобы оптимизировать с 240 секунд до 0,6 для 40 000 городов). Но теперь я застрял на части TSP.

Вот материалы, которые я использовал для изучения TSP:

Я как бы понимаю алгоритм (но не полностью), но у меня проблемы с его реализацией. До этого я занимался динамическим программированием с массивами dp[int] или dp[int][int]. Но теперь, когда моя матрица dp должна быть dp[subset][int], я понятия не имею, как мне это сделать.

Мои вопросы:

  • Как мне обрабатывать подмножества с помощью динамического программирования? (желателен пример на C++)
  • Позволяют ли алгоритмы, которые я связал, посещать города более одного раза, и если нет, что я должен изменить?
  • Должен ли я вместо этого использовать другой алгоритм TSP? (Я заметил, что есть несколько способов сделать это). Имейте в виду, что я должен получить точное значение, а не приблизительное.

Редактировать:

После дополнительных исследований я наткнулся на несколько лекций по соревновательному программированию из Стэнфорда и мне удалось найти TSP здесь (слайды 26-30). Суть в том, чтобы представить подмножество в виде битовой маски. Это все еще оставляет мои другие вопросы без ответа.

Можно ли внести какие-либо изменения в этот алгоритм, чтобы разрешить посещение города более одного раза. Если это возможно, что это за изменения? В противном случае, что я должен попробовать?


person A. Andevski    schedule 16.06.2014    source источник
comment
Я не уверен, но я почти уверен, что вы не можете использовать алгоритм Дейкстры, чтобы получить точное решение задачи о коммивояжере (если только вы не хотите жадного приближения). Имейте в виду, что Дейкстра полиномиален, и ваш ответ должен быть экспоненциальным.   -  person Patrick Collins    schedule 17.06.2014
comment
@PatrickCollins Я не использую Dijkstra, чтобы получить точное решение для TSP. Я только что упомянул, что использовал Dijkstra для создания матрицы связности, которую я буду использовать для TSP. Я планирую сделать TSP с динамическим программированием. Пожалуйста, прочитайте внимательно   -  person A. Andevski    schedule 17.06.2014
comment
Ах, хорошо, я неправильно понял - я думал, что вы хотите использовать алгоритм Дейкстры в качестве шага в реализации TSP. (Что было бы лучше, если бы вы искали жадное приближение)   -  person Patrick Collins    schedule 17.06.2014
comment
Похоже, вам нужно посетить 15 указанных городов, но, пожалуйста, объясните это. То, что у вас есть в настоящее время, может быть легко интерпретировано как «Найти подмножество из 15 городов с самой короткой TSP».   -  person j_random_hacker    schedule 17.06.2014


Ответы (3)


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

person Gigamegs    schedule 17.06.2014
comment
Это действительно сработало для меня без каких-либо корректировок. Первая часть моего алгоритма (Дейкстры, которую я запускал) на самом деле служит для меня Флойдом-Уоршаллом. Простой запуск TSP решил эту проблему. - person A. Andevski; 17.06.2014
comment
Если мой ответ полезен, пожалуйста, примите его. Спасибо! - person Gigamegs; 17.06.2014

Вот реализация TSP, вы найдете ссылку реализованная проблема в посте.

Связанные вами алгоритмы не позволяют посещать города более одного раза.

На ваш третий вопрос я думаю, что ответ Phpdna был хорошим.

person Omar Sebres    schedule 18.06.2014

Можно ли посещать города более одного раза? И да и нет. На первом этапе вы сокращаете задачу до 15 соответствующих городов. В результате получается полный граф, то есть такой, в котором каждый узел соединен с каждым другим узлом. Соединение между двумя такими узлами может включать в себя несколько городов на исходной карте, в том числе некоторые из соответствующих, но это не должно иметь отношения к вашему алгоритму на втором этапе.

Если бы я использовал другой алгоритм, я бы, возможно, выполнил поиск в глубину по графу. Используя минимальное остовное дерево, вы можете дать верхнюю и нижнюю границы оставшимся городам и использовать их для выбора многообещающих решений и отбрасывания безнадежных (так называемое сокращение). На эту тему также было проведено множество исследований, просто поищите в Интернете. Например, в тех случаях, когда карта на самом деле является декартовой (т. е. стоимость проезда — это расстояние между двумя точками на плоскости), вы можете использовать эту информацию, чтобы немного улучшить алгоритмы.

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

person Ulrich Eckhardt    schedule 17.06.2014