-
Notifications
You must be signed in to change notification settings - Fork 19.9k
/
Copy pathTravelingSalesman.java
155 lines (137 loc) · 5.75 KB
/
TravelingSalesman.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package com.thealgorithms.graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* This class provides solutions to the Traveling Salesman Problem (TSP) using both brute-force and dynamic programming approaches.
* For more information, see <a href="https://en.wikipedia.org/wiki/Travelling_salesman_problem">Wikipedia</a>.
* @author <a href="https://github.com/DenizAltunkapan">Deniz Altunkapan</a>
*/
public final class TravelingSalesman {
// Private constructor to prevent instantiation
private TravelingSalesman() {
}
/**
* Solves the Traveling Salesman Problem (TSP) using brute-force approach.
* This method generates all possible permutations of cities, calculates the total distance for each route, and returns the shortest distance found.
*
* @param distanceMatrix A square matrix where element [i][j] represents the distance from city i to city j.
* @return The shortest possible route distance visiting all cities exactly once and returning to the starting city.
*/
public static int bruteForce(int[][] distanceMatrix) {
if (distanceMatrix.length <= 1) {
return 0;
}
List<Integer> cities = new ArrayList<>();
for (int i = 1; i < distanceMatrix.length; i++) {
cities.add(i);
}
List<List<Integer>> permutations = generatePermutations(cities);
int minDistance = Integer.MAX_VALUE;
for (List<Integer> permutation : permutations) {
List<Integer> route = new ArrayList<>();
route.add(0);
route.addAll(permutation);
int currentDistance = calculateDistance(distanceMatrix, route);
if (currentDistance < minDistance) {
minDistance = currentDistance;
}
}
return minDistance;
}
/**
* Computes the total distance of a given route.
*
* @param distanceMatrix A square matrix where element [i][j] represents the
* distance from city i to city j.
* @param route A list representing the order in which the cities are visited.
* @return The total distance of the route, or Integer.MAX_VALUE if the route is invalid.
*/
public static int calculateDistance(int[][] distanceMatrix, List<Integer> route) {
int distance = 0;
for (int i = 0; i < route.size() - 1; i++) {
int d = distanceMatrix[route.get(i)][route.get(i + 1)];
if (d == Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
distance += d;
}
int returnDist = distanceMatrix[route.get(route.size() - 1)][route.get(0)];
return (returnDist == Integer.MAX_VALUE) ? Integer.MAX_VALUE : distance + returnDist;
}
/**
* Generates all permutations of a given list of cities.
*
* @param cities A list of cities to permute.
* @return A list of all possible permutations.
*/
private static List<List<Integer>> generatePermutations(List<Integer> cities) {
List<List<Integer>> permutations = new ArrayList<>();
permute(cities, 0, permutations);
return permutations;
}
/**
* Recursively generates permutations using backtracking.
*
* @param arr The list of cities.
* @param k The current index in the permutation process.
* @param output The list to store generated permutations.
*/
private static void permute(List<Integer> arr, int k, List<List<Integer>> output) {
if (k == arr.size()) {
output.add(new ArrayList<>(arr));
return;
}
for (int i = k; i < arr.size(); i++) {
Collections.swap(arr, i, k);
permute(arr, k + 1, output);
Collections.swap(arr, i, k);
}
}
/**
* Solves the Traveling Salesman Problem (TSP) using dynamic programming with the Held-Karp algorithm.
*
* @param distanceMatrix A square matrix where element [i][j] represents the distance from city i to city j.
* @return The shortest possible route distance visiting all cities exactly once and returning to the starting city.
* @throws IllegalArgumentException if the input matrix is not square.
*/
public static int dynamicProgramming(int[][] distanceMatrix) {
if (distanceMatrix.length == 0) {
return 0;
}
int n = distanceMatrix.length;
for (int[] row : distanceMatrix) {
if (row.length != n) {
throw new IllegalArgumentException("Matrix must be square");
}
}
int[][] dp = new int[n][1 << n];
for (int[] row : dp) {
Arrays.fill(row, Integer.MAX_VALUE);
}
dp[0][1] = 0;
for (int mask = 1; mask < (1 << n); mask++) {
for (int u = 0; u < n; u++) {
if ((mask & (1 << u)) == 0 || dp[u][mask] == Integer.MAX_VALUE) {
continue;
}
for (int v = 0; v < n; v++) {
if ((mask & (1 << v)) != 0 || distanceMatrix[u][v] == Integer.MAX_VALUE) {
continue;
}
int newMask = mask | (1 << v);
dp[v][newMask] = Math.min(dp[v][newMask], dp[u][mask] + distanceMatrix[u][v]);
}
}
}
int minDistance = Integer.MAX_VALUE;
int fullMask = (1 << n) - 1;
for (int i = 1; i < n; i++) {
if (dp[i][fullMask] != Integer.MAX_VALUE && distanceMatrix[i][0] != Integer.MAX_VALUE) {
minDistance = Math.min(minDistance, dp[i][fullMask] + distanceMatrix[i][0]);
}
}
return minDistance == Integer.MAX_VALUE ? 0 : minDistance;
}
}