Imagine you are tasked with designing a delivery robot that operates within a warehouse. The robot's mission is to:
- Start at a designated "home" location.
- Visit every other location exactly once.
- Return to the home location before its battery runs out.
The warehouse layout is represented as an undirected graph G = (V, E):
- Each vertex (v in V) represents a location.
- Each edge ((u, v) in E) represents a direct path between locations (u) and (v).
- (h in V) is the designated home vertex.
- Each location (v in V) (other than (h)) has a delivery time (t(v)).
- The robot must complete its route within a time limit (T), which includes delivery and travel times.
Find a Hamiltonian circuit in (G) that:
- Starts and ends at (h).
- Visits every other vertex exactly once.
- Ensures the total time does not exceed (T).
If such a circuit exists, output the sequence of vertices visited. If not, output NO FEASIBLE CIRCUIT
.
We use a recursive backtracking approach combined with a priority queue for optimal neighbor selection. Below is the pseudocode:
-
Initialize variables:
cost = 0 path = [] visited[V] = [false, false, ..., false] visited[h] = true // h is the home vertex path.add(h) // Start the path with the home vertex call hamiltonCycle(graph, visited, h, path, cost)
-
Function Definition:
bool hamiltonCycle(graph, visited, h, path, cost): if path.size() == V: // Check if the last visited vertex connects back to h if (last_vertex in path has edge to h): display path return true else: return false found = false priority_queue pq for each neighbor of current vertex: if not visited[neighbor]: pq.push(neighbor, weight + graph.TravelCost(current, neighbor)) while not pq.empty() and not found: neighbor = pq.top() pq.pop() visited[neighbor] = true path.add(neighbor) cost += (delivery_time + travel_time) found = hamiltonCycle(graph, visited, h, path, cost) visited[neighbor] = false cost -= (delivery_time + travel_time) path.remove() return found
-
Best Case:
- Priority queue operations: O(V · log V)
- Depth of recursion: O(V)
- Overall: O(V² · log V)
-
Worst Case:
- Exploring all permutations: O(V!)
- Combined complexity: O(V · log V + V!)
- Graph representation: O(V²)
- Auxiliary space (visited array, path vector, priority queue): O(V²)
- Overall: O(V²)
- Graph Definition:
- (V): Set of vertices.
- (E): Set of edges with weights.
- Delivery Times:
- (t(v)): Delivery time for each vertex.
- Time Limit:
- (T): Maximum allowable time.
- Vertices: V = {h, A, B, C}
- Edges: E = {(h, A), (h, B), (h, C), (A, B), (A, C), (B, C)}
- Weights: [2, 2, 3, 4, 5, 8]
- Delivery Times: t(A) = 5, t(B) = 10, t(C) = 8
- Time Limit: T = 38
- Expected Output: (h, B, A, C, h)
- Vertices: V = {h, A, B, C}
- Edges: E = {(h, A), (h, B), (h, C), (A, B), (A, C), (B, C)}
- Weights: [1, 2, 3, 4, 5, 6]
- Delivery Times: t(A) = 5, t(B) = 10, t(C) = 8
- Time Limit: T = 20
- Expected Output: NO FEASIBLE CIRCUIT
The solution has been implemented in C++ and named hcp.cpp
. It processes multiple test cases from input text files.
- Read and parse input files.
- Execute the Hamiltonian Circuit algorithm for each test case.
- Output results for each test case.