import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.StringTokenizer; public class TSPUsingMST { // ArraysC to keep track of info. related to each city private String[] cityName; private String[] cityState; private int[] cityLat; private int[] cityLong; private int[] cityPop; // 2-D array to keep track of pairwise distances between cities private int[][] distances; // number of cities private static int numCities; public TSPUsingMST(int n) { numCities = n; // Allotting the space for each 1-D array cityName = new String[numCities]; cityState = new String[numCities]; cityLat = new int[numCities]; cityLong = new int[numCities]; cityPop = new int[numCities]; // Allocate space for each 2-D array. These arrays have 0 elements in // row 0, // 1 element in row 1, 2 elements in row 2, etc. distances = new int[numCities][]; for (int i = 0; i < numCities; i++) distances[i] = new int[i]; try { // Construct a buffered reader object and connect it to the files // "miles.dat" BufferedReader in = new BufferedReader(new FileReader("miles.dat")); // A counter that keeps track of the index of the current city being // read int cityNumber = 0; // While-loop for reading in data from "miles.dat." At the beginning // of the while-loop // the expectation is that we'll be reading a line containing the // city name. Instead, // if we encounter a line that starts with "*" then we skip to the // next line while (cityNumber < numCities) { // Read in a line String line = in.readLine(); // Skip the rest of the loop if line starts with a "*" if (line.charAt(0) == '*') continue; // Otherwise tokenize the line StringTokenizer tokenizedLine = new StringTokenizer(line, ",[]"); // Putting actual data into correct position in the array cityName[cityNumber] = tokenizedLine.nextToken(); cityState[cityNumber] = (tokenizedLine.nextToken()).trim(); // trim() // gets // rid // of // leading/trailing // blanks cityLat[cityNumber] = Integer.parseInt(tokenizedLine .nextToken()); cityLong[cityNumber] = Integer.parseInt(tokenizedLine .nextToken()); cityPop[cityNumber] = Integer.parseInt(tokenizedLine .nextToken()); // while loop to put distances in the array; this may need to // read several lines int mileNumber = 0; while (mileNumber < cityNumber) { // Read a mileage line and tokenize it String mileage = in.readLine(); StringTokenizer tokenizedMileage = new StringTokenizer( mileage, " "); // Read all the mileage data in this line into row // cityNumber; increment // mileNumber after each read while (tokenizedMileage.hasMoreTokens()) { distances[cityNumber][cityNumber - mileNumber - 1] = Integer .parseInt(tokenizedMileage.nextToken()); mileNumber++; } } // end of while reading distances cityNumber++; } // end of while reading cities in.close(); } // end of try catch (IOException e) { System.out.println("File not found."); } } // end of TSPTester() constructor // A simple getIndex method to help test the constructor int getIndex(String city, String state) { int location; for (location = 0; location < numCities; location++) if ((cityName[location].equals(city)) && (cityState[location].equals(state))) return location; return -1; } // Print information about a city, given a city index void printCityInfo(int index) { System.out .println(cityName[index] + " " + cityState[index] + " " + cityLat[index] + " " + cityLong[index] + " " + cityPop[index]); } // Print distance information between a given pair of cities void printDistanceInfo(int i, int j) { if (i < j) System.out.println(distances[j][i]); else System.out.println(distances[i][j]); } int getDistance(int i, int j) { if (i < j) return distances[j][i]; else if (j < i) return distances[i][j]; else return 0; } int[] greedyTSP() { // Find a cheapest triangle // Load triangle 0-1-2 into the the first 3 slots of the greedy array int[] greedy = new int[numCities]; int currentDistance; greedy[0] = 0; greedy[1] = 1; greedy[2] = 2; int currentBestDistance = getDistance(0, 1) + getDistance(1, 2) + getDistance(2, 0); for (int i = 0; i < numCities; i++) for (int j = 0; j < i; j++) for (int k = 0; k < j; k++) if ((currentDistance = getDistance(i, j) + getDistance(j, k) + getDistance(i, k)) < currentBestDistance) { greedy[0] = i; greedy[1] = j; greedy[2] = k; currentBestDistance = currentDistance; } // Try greedily to add a city that yields the smallest increase // in the cost of the tour int partialTourSize = 3; boolean[] visited = new boolean[numCities]; for (int i = 0; i < numCities; i++) visited[i] = false; visited[greedy[0]] = true; visited[greedy[1]] = true; visited[greedy[2]] = true; // Main loop: keep repeating until partial tour covers all cities while (partialTourSize < numCities) { int smallestIncrease = Integer.MAX_VALUE; int increase = 0; int bestInsertionPoint = 0; int bestCity = 0; // Scan through all cities, stopping at unvisited cities for (int i = 0; i < numCities; i++) { if (!visited[i]) { // Consider all possible positions of inserting city i into // the tour // and record the smallest increase for (int j = 0; j < partialTourSize; j++) { increase = getDistance(greedy[j], i) + getDistance(i, greedy[(j + 1) % numCities]) - getDistance(greedy[j], greedy[(j + 1) % numCities]); if (increase < smallestIncrease) { smallestIncrease = increase; bestCity = i; bestInsertionPoint = j; } // end of if we have found a smaller increase } // end of for-j } // end of if not visited } // end of for-i // Now we are ready to insert the bestCity at the bestInsertionPoint for (int j = partialTourSize - 1; j > bestInsertionPoint; j--) greedy[j + 1] = greedy[j]; greedy[bestInsertionPoint + 1] = bestCity; visited[bestCity] = true; partialTourSize++; } // end-while return greedy; } void copy(int[] source, int[] dest) { for (int i = 0; i < dest.length; i++) dest[i] = source[i]; } void TSP(int[] R, int partialTourSize, boolean[] visited, int[] T) { // Base case: we have discovered a tour better than T if ((partialTourSize == numCities) && (cost(R) < cost(T))) { System.out.println("Base case. Tour cost is " + cost(R)); copy(R, T); return; } // Another base case: our partial tour is not worth completing if (cost(R, partialTourSize) >= cost(T)) return; // Recursive case: R is not complete and is currently better than T // and is therefore worth completing for (int i = 0; i < numCities; i++) { if (!visited[i]) { // System.out.println("Appending " + i); visited[i] = true; R[partialTourSize++] = i; TSP(R, partialTourSize, visited, T); partialTourSize--; visited[i] = false; // System.out.println("Deleting " + i); } } // end of for-loop } // end of TSP double cost(int[] tour) { return cost(tour, tour.length); } double cost(int[] tour, int tourSize) { double c = 0; for (int i = 0; i < tourSize - 1; i++) c = c + getDistance(tour[i], tour[i + 1]); c = c + getDistance(tour[tourSize - 1], tour[0]); return c; } // Main method public static void main(String[] args) { int n = 15; TSPUsingMST T = new TSPUsingMST(n); // Initialize the list of vertices in the tree // Initially, no one except vertex 0 is in the tree boolean[] visited = new boolean[n]; for (int i = 0; i < n; i++) visited[i] = false; visited[0] = true; // Initialize the int[] that maintains the tree to default values // No vertices have parents set, except vertex 0 whose parent is itself int[] tree = new int[n]; for (int i = 0; i < n; i++) tree[i] = -1; tree[0] = 0; for (int i = 1; i <= n - 1; i++) { long minWeight = Long.MAX_VALUE; int bestVertex = -1; int bestParent = -1; for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { if ((visited[j]) && (!visited[k])) { if (T.getDistance(j, k) < minWeight) { minWeight = T.getDistance(j, k); bestVertex = k; bestParent = j; } // end if better distance is found } // end if an edge between a visited and an unvisited is // found } // end for-k } // end for-j // Update visited and tree visited[bestVertex] = true; tree[bestVertex] = bestParent; } // end for-i // Printing the MST for (int i = 1; i < n; i++) System.out.println(T.cityName[i] + " " + T.cityState[i] + ", " + T.cityName[tree[i]] + " " + T.cityState[tree[i]]); // Compting the MST cost long cost = 0; for (int i = 0; i < n; i++) cost += T.getDistance(i, tree[i]); System.out.println("The cost of the minimum spanning tree is " + cost); } // end main method } // end class /* Yankton SD, Wisconsin Dells WI Yakima WA, Williston ND Worcester MA, Wilmington DE Wisconsin Dells WI, Youngstown OH Winston-Salem NC, Winchester VA Winnipeg MB, Yankton SD Winchester VA, Wilmington DE Wilmington NC, Winston-Salem NC Wilmington DE, Williamsport PA Williston ND, Winnipeg MB Williamsport PA, Youngstown OH Williamson WV, Winston-Salem NC Wichita Falls TX, Wichita KS Wichita KS, Yankton SD The cost of the minimum spanning tree is 5461