Путешественник должен посетить все города из списка, где известны расстояния между всеми городами, и каждый город должен быть посещен только один раз. По какому кратчайшему маршруту он посещает каждый город ровно один раз и возвращается в исходный город?
Решение
Проблема коммивояжера — самая известная вычислительная проблема. Мы можем использовать метод грубой силы, чтобы оценить каждый возможный тур и выбрать лучший. Для n числа вершин в графе существует ( n — 1)! количество возможностей.
Вместо грубой силы, использующей подход динамического программирования, решение может быть получено за меньшее время, хотя нет алгоритма полиномиального времени.
Рассмотрим граф G = (V, E) , где V — множество городов, а E — множество взвешенных ребер. Ребро e (u, v) обозначает, что вершины u и v связаны. Расстояние между вершиной u и v равно d (u, v) , что должно быть неотрицательным.
Предположим, мы начали с города 1 и, посетив некоторые города, теперь мы находимся в городе j . Следовательно, это частичный тур. Нам, безусловно, нужно знать j , так как это определит, какие города удобнее всего посетить в следующем. Нам также нужно знать все города, которые мы посетили, чтобы не повторять ни один из них. Следовательно, это соответствующая подзадача.
Для подмножества городов S Є {1, 2, 3, …, n}, которое включает 1 , и j Є S , пусть C (S, j) будет длина кратчайшего пути, посещающего каждый узел в S ровно один раз начиная с 1 и заканчивая j .
Когда | S | > 1, мы определяем C (S, 1) = ∝, поскольку путь не может начинаться и заканчиваться на 1 .
Теперь, давайте выразим C (S, j) в терминах меньших подзадач. Нам нужно начинать с 1 и заканчивать на j . Мы должны выбрать следующий город таким образом, чтобы
C(S,j)=minC(S− lbracej rbrace,i)+d(i,j)гдеi inSиi neqjc(S,j)=minC(s− lbracej rbrace,i)+d(i,j)гдеi inSиi neqj
Algorithm: Traveling-Salesman-Problem C ({1}, 1) = 0 for s = 2 to n do for all subsets S Є {1, 2, 3, … , n} of size s and containing 1 C (S, 1) = ∞ for all j Є S and j ≠ 1 C (S, j) = min {C (S – {j}, i) + d(i, j) for i Є S and i ≠ j} Return minj C ({1, 2, 3, …, n}, j) + d(j, i)
Анализ
Существует не более 2nn подзадач, каждая из которых требует линейного времени для решения. Следовательно, общее время работы составляет O(2nn2).
пример
В следующем примере мы проиллюстрируем шаги для решения проблемы коммивояжера.
Из приведенного выше графика подготовлена следующая таблица.
1 | 2 | 3 | 4 | |
1 | 0 | 10 | 15 | 20 |
2 | 5 | 0 | 9 | 10 |
3 | 6 | 13 | 0 | 12 |
4 | 8 | 8 | 9 | 0 |
S = Φ
smallCost(2, Phi,1)=d(2,1)=5 smallCost(2, Phi,1)=d(2,1)=5
smallCost(3, Phi,1)=d(3,1)=6 smallCost(3, Phi,1)=d(3,1)=6
smallCost(4, Phi,1)=d(4,1)=8 smallCost(4, Phi,1)=d(4,1)=8
S = 1
smallCost(i,s)=min lbraceCost(j,s−(j))+d[i,j] rbrace smallCost(i,s)=min lbraceCost(j,s)−(j))+d[i,j] rbrace
smallCost(2, lbrace3 rbrace,1)=d[2,3]+Cost(3, Phi,1)=9+6=15стоимости(2, lbrace3 rbrace,1)=d[2,3]+стоимость(3, Phi,1)=9+6=15
smallCost(2, lbrace4 rbrace,1)=d[2,4]+Cost(4, Phi,1)=10+8=18cost(2, lbrace4 rbrace,1)=д[2,4]+стоимость(4, Фи,1)=10+8=18
smallCost(3, lbrace2 rbrace,1)=d[3,2]+Cost(2, Phi,1)=13+5=18ccost(3, lbrace2 rbrace,1)=d[3,2]+стоимость(2, Фи,1)=13+5=18
smallCost(3, lbrace4 rbrace,1)=d[3,4]+Cost(4, Phi,1)=12+8=20стоимости(3, lbrace4 rbrace,1)=д[3,4]+стоимость(4, Фи,1)=12+8=20
smallCost(4, lbrace3 rbrace,1)=d[4,3]+Cost(3, Phi,1)=9+6=15стоимости(4, lbrace3 rbrace,1)=д[4,3]+стоимость(3, Фи,1)=9+6=15
smallCost(4, lbrace2 rbrace,1)=d[4,2]+Cost(2, Phi,1)=8+5=13cost(4, lbrace2 rbrace,1)=д[4,2]+стоимость(2, Фи,1)=8+5=13
S = 2
smallCost(2, lbrace3,4 rbrace,1)= begincased[2,3]+Стоимость(3, lbrace4 rbrace,1)=9+20=29 d[2,4]+Стоимость(4, lbrace3 rbrace,1)=10+15=25=25 smallСтоимость(2, lbrace3,4 rbrace,1) lbraced[2,3]+ smallcost(3, lbrace4 rbrace,1)=9+20=29d[2,4]+ smallCost(4, lbrace3 rbrace,1)=10+15=25 endcase=25
smallCost(3, lbrace2,4 rbrace,1)= begincased[3,2]+Cost(2, lbrace4 rbrace,1)=13+18=31 d[3,4]+Стоимость(4, lbrace2 rbrace,1)=12+13=25=25 smallСтоимость(3, lbrace2,4 rbrace,1) lbraced[3,2]+ smallcost(2, lbrace4 rbrace,1)=13+18=31d[3,4]+ smallCost(4, lbrace2 rbrace,1)=12+13=25 endcase=25
smallCost(4, lbrace2,3 rbrace,1)= begincased[4,2]+Cost(2, lbrace3 rbrace,1)=8+15=23 d[4,3]+Cost(3, lbrace2 rbrace,1)=9+18=27=23 smallСтоимость(4, lbrace2,3 rbrace,1) lbraced[4,2]+ smallcost(2, lbrace3 rbrace,1)=8+15=23d[4,3]+ smallCost(3, lbrace2 rbrace,1)=9+18=27 endcase=23
S = 3
smallCost(1, lbrace2,3,4 rbrace,1)= begincased[1,2]+Стоимость(2, lbrace3,4 rbrace,1)=10+25=35 d[1,3]+Стоимость(3, lbrace2,4 rbrace,1)=15+25=40d[1,4]+Стоимость(4, lbrace2,31)=20+23=43=35затрат(1,2,3,4,4),1) 1,2[+]стоимости(23,4,4),1)=10+25=35 d[1,3]+стоимость(3,2,4фунта,1)=15+25=40 1,4[+]+стоимость(4, lbrace2,3 rbrace,1)=20+23=43=35 endcase
Минимальная стоимость пути составляет 35.
Начнем со стоимости {1, {2, 3, 4}, 1} , получим минимальное значение для d [1, 2] . Когда s = 3 , выберите путь от 1 до 2 (стоимость 10), затем вернитесь назад. Когда s = 2 , мы получаем минимальное значение для d [4, 2] . Выберите путь от 2 до 4 (стоимость 10), затем идите назад.
Когда s = 1 , мы получаем минимальное значение для d [4, 3] . Выбрав путь от 4 до 3 (стоимость 9), мы перейдем к шагу s = Φ . Получаем минимальное значение для d [3, 1] (стоимость 6).