/// <summary> /// Calculates the shortest route between two towns. /// </summary> /// <remarks> /// Performs this calculation by finding the route between two nodes with the smallest /// sum of edge weights. /// </remarks> /// <param name="outputNum">The output case number the program is currently on.</param> /// <param name="startTown">The starting town where route calculations begin.</param> /// <param name="endTown">The final town in a valid route.</param> /// <param name="map">The DirectedGraph object representing the map of train routes.</param> private static void ShortestRoute(int outputNum, char startTown, char endTown, DirectedGraph map) { Node startNode = map.GetNode(startTown); int minDistance = Int32.MaxValue; // init the minDistance to the highest possible value // Iterative DFS with stack // The third item in each tuple counts the distance already // traveled in the current route. // Useful when the same node is accessed multiple times // by multiple routes. // The second item in each tuple counts how many stops the route // has already made from that Node. // Used to prevent infinite loops while minDistance is still MaxValue. Stack <Tuple <Node, int, int> > stack = new Stack <Tuple <Node, int, int> >(); stack.Push(new Tuple <Node, int, int>(startNode, 0, 0)); // Is the program in its first iteration of the loop? // Used to prevent cases where startTown = endTown and a route with // distance = 0 is recognized. bool firstIteration = true; while (stack.Count > 0) { Node currentNode = stack.Peek().Item1; int stopsCounter = stack.Peek().Item2; int distanceCount = stack.Peek().Item3; stack.Pop(); // If the current node is the end town (and this isn't the loop's first iteration), // then a valid route was found. // Compare the distanceCount of the current route to minDistance. if (currentNode.Name == endTown && !firstIteration && distanceCount < minDistance) { minDistance = distanceCount; } stopsCounter++; // If a valid route hasn't been found yet with the current node AND the number of stops // in the current route is <= the number of stops in the map... // ("stopsCounter <= map.Nodes.Count" is used to prevent the loop from infinitely // adding a cycle of nodes to the stack while minDistance = maxValue) if (stopsCounter <= map.Nodes.Count && (firstIteration || currentNode.Name != endTown)) { // Add all adjacent nodes/towns to the stack with the updated stopsCounter and distanceCount foreach (Edge edge in currentNode.Edges) { stack.Push(new Tuple <Node, int, int>(edge.Node, stopsCounter, distanceCount + edge.Weight)); } firstIteration = false; } } if (minDistance == Int32.MaxValue) { Print(outputNum, NO_ROUTE); // If a route was found, then minDistance < Int32.MaxValue } else { Print(outputNum, minDistance.ToString()); } }
/// <summary> /// Calculates how many routes exist from one town to another with either at most or /// exactly n number of stops. /// </summary> /// <param name="outputNum">The output case number the program is currently on.</param> /// <param name="startTown">The starting town where route calculations begin.</param> /// <param name="endTown">The final town in a valid route.</param> /// <param name="numStops">Either the exact number or maximum number of stops a route /// can have, depending on the value of compareMode.</param> /// <param name="compareMode">The string specifying what calculation this method will /// be performing. If set to "max", the method will calculate the number of routes that /// have at most numStops number of stops. If set to "exactly", will calculate the number /// of routes that have exactly numStops number of stops.</param> /// <param name="map">The DirectedGraph object representing the map of train routes.</param> private static void NumTripsByStops(int outputNum, char startTown, char endTown, int numStops, string compareMode, DirectedGraph map) { Node startNode = map.GetNode(startTown); if (numStops < 0) { Print(outputNum, "ERROR: Cannot calculate routes using a negative number of stops."); return; } // Iterative DFS with stack // The second item in each tuple counts how many stops the route // has already made from that Node. // Very important, since the same Node can be accessed // multiple times by multiple routes. Stack <Tuple <Node, int> > stack = new Stack <Tuple <Node, int> >(); stack.Push(new Tuple <Node, int>(startNode, 0)); // Is the program in its first iteration of the loop? // Used to prevent cases where startTown = endTown and a route with // 0 stops is recognized. bool firstIteration = true; int routeCount = 0; while (stack.Count > 0) { Node currentNode = stack.Peek().Item1; int stopsCounter = stack.Peek().Item2; stack.Pop(); // If the current node is the end town, then a route has reached from the start town // to the end town within numStops stops. // Check the compareMode value. For compareMode = "exactly", only increment if // the route got to the end town in exactly numStops stops. if (currentNode.Name == endTown && !firstIteration && (compareMode == "max" || (compareMode == "exactly" && stopsCounter == numStops))) { routeCount++; } stopsCounter++; firstIteration = false; // If the current route's number of stops <= the number of stops // specified for the problem, add all adjacent Nodes to the stack with // the number of stops incremented for those possible routes. if (stopsCounter <= numStops) { foreach (Edge edge in currentNode.Edges) { stack.Push(new Tuple <Node, int>(edge.Node, stopsCounter)); } } } Print(outputNum, routeCount.ToString()); }