Heuristic search did not click for me from formulas.
It clicked when I drew a grid, blocked a few cells, and watched the algorithm make greedy decisions that looked smart until they were not.
Here is the problem:
S . . # .
. # . # .
. # . . .
. . . # G
S is the start. G is the goal. # is blocked.
The question is simple: which cell should we try next?
The Mental Model
A heuristic is a guess.
For grid movement, a common guess is Manhattan distance:
h(n) = abs(n.x - goal.x) + abs(n.y - goal.y)
It says: "How many horizontal/vertical steps would it take if walls did not exist?"
That "if walls did not exist" part matters. The heuristic is useful, but it is not the full truth.
Greedy Best-First Search
Greedy search uses only the guess:
priority = h(n)
It always chases the cell that looks closest to the goal.
That can be fast. It can also walk straight into a wall and waste time because it ignores how expensive the path already was.
Small Python-style sketch:
from heapq import heappush, heappop
def greedy(start, goal, neighbors):
open_set = []
heappush(open_set, (0, start))
visited = set()
while open_set:
_, node = heappop(open_set)
if node == goal:
return True
if node in visited:
continue
visited.add(node)
for next_node in neighbors(node):
if next_node not in visited:
heappush(open_set, (manhattan(next_node, goal), next_node))
return False
This is simple, but it is not guaranteed to find the cheapest path.
A* Search
A* uses two numbers:
g(n) = cost from start to current node
h(n) = estimated cost from current node to goal
f(n) = g(n) + h(n)
That is the practical difference.
Greedy says:
Which node looks closest to the goal?
A* says:
Which node gives the best total path estimate?
def astar(start, goal, neighbors):
open_set = []
heappush(open_set, (0, start))
came_from = {}
g_score = {start: 0}
while open_set:
_, node = heappop(open_set)
if node == goal:
return rebuild_path(came_from, node)
for next_node in neighbors(node):
tentative = g_score[node] + 1
if tentative < g_score.get(next_node, float("inf")):
came_from[next_node] = node
g_score[next_node] = tentative
f_score = tentative + manhattan(next_node, goal)
heappush(open_set, (f_score, next_node))
return None
This is the version I would actually teach first.
Why the Heuristic Matters
If the heuristic is too weak, A* behaves more like Dijkstra's algorithm and explores too much.
If the heuristic overestimates, A* can become fast but lose optimality.
The useful property is admissibility:
h(n) <= real remaining cost
In plain English: the heuristic is allowed to be optimistic, but it should not lie by saying the goal is farther than it really is.
Where Developers Actually See This
Heuristic search shows up in:
- game pathfinding
- robot movement
- route planning
- scheduling
- puzzle solving
- AI agent planning
For 2026 AI agent systems, this mental model is becoming useful again. A planning agent often needs to choose the next tool call or search path without brute-forcing every option. The same old idea applies: a decent heuristic can save a lot of wasted exploration.
What I Would Avoid
I would not start by memorizing every search algorithm.
Start with these three:
| Algorithm | Uses cost so far? | Uses heuristic? | Finds shortest path? |
|---|---|---|---|
| Dijkstra | yes | no | yes |
| Greedy Best-First | no | yes | not always |
| A* | yes | yes | yes, with a good heuristic |
That table clears up most confusion.
Final Thought
Heuristic search is not magic AI. It is controlled guessing.
The engineering skill is choosing a guess that is cheap, useful, and honest enough for the problem.
Where have you used A* or heuristic search outside a textbook example?
Top comments (0)