📜  旅行商问题 (TSP) 实施

📅  最后修改于: 2022-05-13 01:57:54.464000             🧑  作者: Mango

旅行商问题 (TSP) 实施

旅行商问题(TSP):给定一组城市和每对城市之间的距离,问题是找到最短的可能路线,该路线恰好访问每个城市一次并返回起点。
注意哈密顿循环和 TSP 之间的区别。哈密顿循环问题是找出是否存在一个游览每个城市恰好一次的游览。在这里我们知道 Hamiltonian Tour 存在(因为图是完整的),实际上存在很多这样的 tours,问题是要找到一个最小权重的 Hamiltonian Cycle。
例如,考虑右侧图中所示的图表。图中的 TSP 巡回是 1-2-4-3-1。旅游费用为10+25+30+15,即80。
这个问题是一个著名的 NP-hard 问题。这个问题没有多项式时间已知的解决方案。

例子:

Output of Given Graph:
minimum weight Hamiltonian Cycle :
10 + 25 + 30 + 15 := 80

在这篇文章中,讨论了一个简单解决方案的实现。

  1. 将城市 1 视为起点和终点。由于路线是循环的,我们可以将任何点视为起点。
  2. 生成所有(n-1)!城市的排列。
  3. 计算每个排列的成本并跟踪最小成本排列。
  4. 以最小成本返回排列。

下面是上述想法的实现

C++
// CPP program to implement traveling salesman
// problem using naive approach.
#include 
using namespace std;
#define V 4
 
// implementation of traveling Salesman Problem
int travllingSalesmanProblem(int graph[][V], int s)
{
    // store all vertex apart from source vertex
    vector vertex;
    for (int i = 0; i < V; i++)
        if (i != s)
            vertex.push_back(i);
 
    // store minimum weight Hamiltonian Cycle.
    int min_path = INT_MAX;
    do {
 
        // store current Path weight(cost)
        int current_pathweight = 0;
 
        // compute current path weight
        int k = s;
        for (int i = 0; i < vertex.size(); i++) {
            current_pathweight += graph[k][vertex[i]];
            k = vertex[i];
        }
        current_pathweight += graph[k][s];
 
        // update minimum
        min_path = min(min_path, current_pathweight);
 
    } while (
        next_permutation(vertex.begin(), vertex.end()));
 
    return min_path;
}
 
// Driver Code
int main()
{
    // matrix representation of graph
    int graph[][V] = { { 0, 10, 15, 20 },
                       { 10, 0, 35, 25 },
                       { 15, 35, 0, 30 },
                       { 20, 25, 30, 0 } };
    int s = 0;
    cout << travllingSalesmanProblem(graph, s) << endl;
    return 0;
}


Java
// Java program to implement
// traveling salesman problem
// using naive approach.
import java.util.*;
class GFG{
     
static int V = 4;
 
// implementation of traveling
// Salesman Problem
static int travllingSalesmanProblem(int graph[][],
                                    int s)
{
  // store all vertex apart
  // from source vertex
  ArrayList vertex =
            new ArrayList();
   
  for (int i = 0; i < V; i++)
    if (i != s)
      vertex.add(i);
 
  // store minimum weight
  // Hamiltonian Cycle.
  int min_path = Integer.MAX_VALUE;
  do
  {
    // store current Path weight(cost)
    int current_pathweight = 0;
 
    // compute current path weight
    int k = s;
     
    for (int i = 0;
             i < vertex.size(); i++)
    {
      current_pathweight +=
              graph[k][vertex.get(i)];
      k = vertex.get(i);
    }
    current_pathweight += graph[k][s];
 
    // update minimum
    min_path = Math.min(min_path,
                        current_pathweight);
 
  } while (findNextPermutation(vertex));
 
  return min_path;
}
 
// Function to swap the data
// present in the left and right indices
public static ArrayList swap(
              ArrayList data,
              int left, int right)
{
  // Swap the data
  int temp = data.get(left);
  data.set(left, data.get(right));
  data.set(right, temp);
 
  // Return the updated array
  return data;
}
   
// Function to reverse the sub-array
// starting from left to the right
// both inclusive
public static ArrayList reverse(
              ArrayList data,
              int left, int right)
{
  // Reverse the sub-array
  while (left < right)
  {
    int temp = data.get(left);
    data.set(left++,
             data.get(right));
    data.set(right--, temp);
  }
 
  // Return the updated array
  return data;
}
   
// Function to find the next permutation
// of the given integer array
public static boolean findNextPermutation(
                      ArrayList data)
{ 
  // If the given dataset is empty
  // or contains only one element
  // next_permutation is not possible
  if (data.size() <= 1)
    return false;
 
  int last = data.size() - 2;
 
  // find the longest non-increasing
  // suffix and find the pivot
  while (last >= 0)
  {
    if (data.get(last) <
        data.get(last + 1))
    {
      break;
    }
    last--;
  }
 
  // If there is no increasing pair
  // there is no higher order permutation
  if (last < 0)
    return false;
 
  int nextGreater = data.size() - 1;
 
  // Find the rightmost successor
  // to the pivot
  for (int i = data.size() - 1;
           i > last; i--) {
    if (data.get(i) >
        data.get(last))
    {
      nextGreater = i;
      break;
    }
  }
 
  // Swap the successor and
  // the pivot
  data = swap(data,
              nextGreater, last);
 
  // Reverse the suffix
  data = reverse(data, last + 1,
                 data.size() - 1);
 
  // Return true as the
  // next_permutation is done
  return true;
}
 
// Driver Code
public static void main(String args[])
{
  // matrix representation of graph
  int graph[][] = {{0, 10, 15, 20},
                   {10, 0, 35, 25},
                   {15, 35, 0, 30},
                   {20, 25, 30, 0}};
  int s = 0;
  System.out.println(
  travllingSalesmanProblem(graph, s));
}
}
 
// This code is contributed by adityapande88


Python3
# Python3 program to implement traveling salesman
# problem using naive approach.
from sys import maxsize
from itertools import permutations
V = 4
 
# implementation of traveling Salesman Problem
def travellingSalesmanProblem(graph, s):
 
    # store all vertex apart from source vertex
    vertex = []
    for i in range(V):
        if i != s:
            vertex.append(i)
 
    # store minimum weight Hamiltonian Cycle
    min_path = maxsize
    next_permutation=permutations(vertex)
    for i in next_permutation:
 
        # store current Path weight(cost)
        current_pathweight = 0
 
        # compute current path weight
        k = s
        for j in i:
            current_pathweight += graph[k][j]
            k = j
        current_pathweight += graph[k][s]
 
        # update minimum
        min_path = min(min_path, current_pathweight)
         
    return min_path
 
 
# Driver Code
if __name__ == "__main__":
 
    # matrix representation of graph
    graph = [[0, 10, 15, 20], [10, 0, 35, 25],
            [15, 35, 0, 30], [20, 25, 30, 0]]
    s = 0
    print(travellingSalesmanProblem(graph, s))


输出
80