How Heap and Recursion Can Select the Best Tourist Attractions
The article explains how to use a max‑heap together with backtracking and a greedy strategy in Python to recommend the top three attractions with the highest scores while keeping the total travel distance under 20 km, and discusses the algorithm's steps, example execution, and limitations.
The problem is to recommend the three highest‑rated tourist attractions from a list, ensuring that the sum of their straight‑line distances from the visitor’s current location does not exceed 20 km. Each attraction is represented by a name, a rating (1–10), and a distance in kilometers.
Algorithm Design
The solution combines three techniques:
Use a priority queue (implemented as a max‑heap) to always consider the highest‑scoring attractions first.
Apply a backtracking search to explore different combinations and enforce the distance constraint.
Employ a greedy rule that stops the search as soon as a valid combination of three attractions is found.
Python Implementation
import heapq
def recommend_attractions(attractions, max_distance=20, num_recommendations=3):
# Build a list of tuples (negative_score, name, distance) for max‑heap behavior
pq = [(-score, name, distance) for name, score, distance in attractions]
heapq.heapify(pq)
def backtrack(index, current_distance, path):
if len(path) == num_recommendations:
return path
for i in range(index, len(pq)):
score, name, distance = pq[i]
if current_distance + distance <= max_distance:
result = backtrack(i + 1, current_distance + distance,
path + [(name, -score, distance)])
if result:
return result
return None
return backtrack(0, 0, [])
# Example data
attractions = [
('Attraction A', 9, 5),
('Attraction B', 8, 8),
('Attraction C', 7, 3),
('Attraction D', 10, 13),
('Attraction E', 6, 2),
('Attraction F', 8, 4),
]
result = recommend_attractions(attractions)
if result:
print("Recommended attractions:")
for name, score, distance in result:
print(f"{name}: rating {score}, distance {distance}km")
else:
print("No suitable attractions found")Explanation of Key Steps
The list comprehension creates tuples with the rating negated so that heapq (a min‑heap) behaves as a max‑heap. heapq.heapify(pq) transforms the list into a heap, placing the highest rating at the top.
The inner backtrack function receives the current index in the heap, the accumulated distance, and the current path of selected attractions.
If the path already contains three attractions, it is returned as a valid solution.
The for loop iterates from the current index to the end of the heap, ensuring each attraction is considered at most once.
When adding an attraction would keep the total distance within the limit, the function recurses with the updated distance and path.
When a recursive call finds a valid combination, return result propagates the solution up the call stack, terminating further exploration.
Step‑by‑Step Example
Using a smaller input:
attractions = [
('A', 9, 5),
('B', 8, 8),
('C', 7, 3),
('D', 10, 7),
]
max_distance = 20
num_recommendations = 3Execution proceeds as follows:
Heap creation yields [(-10, 'D', 7), (-9, 'A', 5), (-8, 'B', 8), (-7, 'C', 3)] and heapq.heapify arranges it as a heap. backtrack(0, 0, []) starts the search.
First level picks D (distance 7), recurses to backtrack(1, 7, [('D', 10, 7)]).
Second level picks A (distance 5), recurses to backtrack(2, 12, [('D', 10, 7), ('A', 9, 5)]).
Third level picks B (distance 8), reaching total distance 20, which satisfies the limit, so the path [('D', 10, 7), ('A', 9, 5), ('B', 8, 8)] is returned.
The result propagates back through each recursion level and is finally returned by recommend_attractions.
Limitations and Performance Considerations
If a chosen attraction would exceed the distance limit, that branch returns None and the algorithm tries the next candidate.
The current implementation traverses the heap by index order, so it does not fully exploit the heap’s ability to pop the maximum element efficiently.
The algorithm stops after finding the first feasible combination, which may not be the optimal solution in terms of total rating or distance utilization.
Finding the true optimal set would require exploring all combinations, leading to exponential time complexity for large datasets; more advanced heuristics or dynamic programming would be needed in that case.
Overall, the approach demonstrates how a max‑heap can prioritize high‑score items while a backtracking search enforces a global constraint, providing a clear, educational example of combining data structures and algorithmic techniques.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
