단원 홈
1단원 · 6차시

지나온 길과 남은 길을 저울에
f = g + h

지난 시간 나침반만 쥔 탐색은 20칸만 보고 길을 찾았지만 19걸음을 걸었습니다. 최단은 17걸음이었지요. 빠르기와 최선 중 하나를 꼭 버려야 할까요? 오늘은 둘을 한 저울에 올리는 식 하나를 배웁니다.

성취기준 12인기01-03 성취기준 12인기01-04
g · 지나온 비용h · 남은 어림 f = g + hA* 허용 가능성h 배율 w
🎯 학습 목표
  • 칸마다 매겨지는 g · h · f가 각각 무엇인지 말하고, 주어진 칸의 f를 직접 계산할 수 있다.
  • f가 가장 작은 칸을 먼저 꺼낸다는 한 줄 규칙으로 A*의 다음 한 걸음을 예측할 수 있다.
  • h 배율을 바꿔 가며 둘러본 칸 수가 꺾이는 문턱과 최단이 깨지는 문턱을 스스로 찾아내고, 그 둘이 다른 자리에 있음을 설명할 수 있다.
🤔

여는 장면 — 두 번의 실패, 그리고 저울

우리는 같은 미로를 벌써 네 번 지나왔습니다. 7행 12열, 벽이 아닌 칸이 65칸, 출발 S에서 목표 G까지 최단은 17걸음인 그 미로입니다. 네 번의 성적표를 나란히 놓아 봅시다.

언제방법둘러본 칸경로 길이최단인가
4차시너비 우선(BFS) — 큐64 17걸음O
4차시깊이 우선(DFS) — 스택22 19걸음X
5차시탐욕적 탐색 — 남은 어림 h만20 19걸음X
오늘?? ??
같은 미로(빈칸 65칸·최단 17걸음)에서 잰 값입니다.

표가 말하는 것은 딱 하나입니다. 지금까지는 둘 중 하나만 가졌습니다. 너비 우선은 최단을 지켰지만 65칸 중 64칸을 다 헤집었습니다. 미로 전체를 거의 통째로 본 셈이지요. 탐욕적 탐색은 20칸만 보고 끝냈지만, 내놓은 길은 최단보다 2걸음 긴 19걸음이었습니다.

2걸음이 대수냐고 물을 수 있습니다. 미로에서는 그럴지 몰라도, 이 미로가 배달 로봇이 도는 건물 도면이라면 이야기가 달라집니다. 하루에 300번 왕복하는 로봇에게 한 번에 2걸음은 하루 600걸음입니다. 반대로 게임 속 유닛 200기가 동시에 길을 찾는다면, 한 기당 64칸을 뒤지는 계산은 화면을 멈추게 만듭니다. 어느 쪽도 그냥 버릴 수 없다는 것이 오늘의 출발점입니다.

💭 오늘의 물음

빠르기와 최선 중 하나를 꼭 버려야 할까?
둘을 한 저울에 같이 올리는 방법은 없을까?

답을 미리 말해 두겠습니다. 있습니다. 그리고 그 방법은 놀랄 만큼 짧습니다 — 덧셈 하나입니다. 지나온 길의 길이와 남은 길의 어림을 더해서, 그 합이 가장 작은 칸을 먼저 봅니다. 이것이 오늘 배울 A*(에이 스타)의 전부예요.

믿기 어렵다면 잠시 의심을 품어 두세요. 오늘 15분 동안 여러분은 이 덧셈을 한 걸음씩 눈으로 따라가며 확인하고, 덧셈의 한쪽에 배율을 곱해 일부러 망가뜨려 볼 것입니다. 망가지는 지점이 어디인지는 아무도 알려 주지 않습니다. 여러분이 슬라이더를 0.1씩 밀어 가며 직접 찾아냅니다.

1

칸마다 세 숫자를 적는다 — g, h, 그리고 f

4차시의 너비 우선 탐색은 칸에 아무것도 적지 않았습니다. 그냥 줄을 세워 차례로 꺼냈지요. 5차시의 탐욕적 탐색은 칸마다 숫자 하나를 적었습니다 — 남은 어림 h였습니다. 오늘 A*는 칸마다 숫자 셋을 적습니다.

g 5 h 12 17 f = g + h g — 지나온 비용 시작점에서 여기까지 실제로 걸은 걸음 수. 이미 지나왔으니 어림이 아니라 정확한 값이다. h — 남은 어림 여기서 목표까지 남았다고 어림한 걸음 수. 벽을 무시하고 잰 맨해튼 거리를 쓴다. f — 둘의 합 이 칸을 지나가는 길 전체의 길이 어림. 작을수록 유망한 칸이다.

그림 1. 오늘 시뮬레이터의 칸 하나. 여기 적힌 (5, 12, 17)은 미로의 (0,5) 칸에서 실제로 나오는 값입니다.

세 숫자를 다시 한 문장씩으로 정리합시다.

  • g — 지나온 비용. 시작점에서 이 칸까지 실제로 걸은 걸음 수입니다. 뒤를 돌아보고 세는 값이라 정확합니다.
  • h — 남은 어림. 이 칸에서 목표까지 남았다고 짐작하는 걸음 수입니다. 5차시에서 쓴 맨해튼 거리, 곧 |행 차이| + |열 차이|를 그대로 씁니다. 앞을 내다보는 값이라 틀릴 수 있습니다.
  • f = g + h — 길 전체의 어림. "이 칸을 거쳐서 목표까지 가면 대략 몇 걸음이 되는가"입니다. 뒤(g)와 앞(h)을 한 줄에 놓은 값이지요.

왜 하필 더하는 걸까요? 지도를 놓고 생각하면 당연합니다. 집에서 학교까지 가는 길에 편의점을 들른다고 합시다. 그 길의 전체 길이는 집→편의점 거리와 편의점→학교 거리를 더한 값입니다. 앞의 것은 이미 걸었으니 정확하고, 뒤의 것은 아직 안 걸었으니 어림입니다. f는 '이 편의점을 들르는 길'의 전체 길이를 어림한 값인 셈이에요.

여기서 5차시와 결정적으로 갈라집니다. 탐욕적 탐색은 h만 봤습니다. "학교에서 가까운 편의점"만 골랐다는 뜻이지요. 그러면 집에서 아무리 멀어도 상관없게 됩니다. 실제로 그렇게 골랐다가 2걸음을 더 걸었습니다. 반대로 g만 보는 것은 "집에서 가까운 편의점"만 고르는 것입니다. 학교 반대 방향이어도 신경 쓰지 않습니다. 둘 다 반쪽입니다.

💡 손으로 한 칸 계산해 보기

미로에서 목표 G는 (6,11)에 있습니다. (0,5) 칸의 h를 구해 봅시다.

h = |0 − 6| + |5 − 11| = 6 + 6 = 12

그리고 시작점에서 (0,5)까지는 오른쪽으로 다섯 칸, 곧 g = 5입니다. 그래서 f = 5 + 12 = 17. 그림 1의 세 숫자가 바로 이것입니다.

이제 놀라운 사실 하나를 미리 봅시다. 이 미로의 최단 경로 위에 있는 칸 18개는 f가 전부 17입니다. 몇 개만 옮겨 적어 보겠습니다.

칸ghf = g + h어디쯤인가
(0,0) S01717출발점
(0,5)51217윗줄을 다섯 칸 지나서
(1,9)10717둘째 줄 오른쪽
(3,10)13417오른쪽 세로 통로
(6,10)16117목표 바로 왼쪽
(6,11) G17017목표
최단 경로 18칸 전부에서 f = 17. 오늘 시뮬레이터로 직접 확인합니다.

우연이 아닙니다. 한 걸음 나아갈 때마다 g는 1 늘고 h는 1 줄기 때문입니다. 최단 경로 위에서는 한 걸음이 정확히 목표에 1만큼 다가가는 걸음이니까요. 그래서 합은 그대로 유지됩니다. f = 17은 이 길의 '이름표'인 셈입니다.

그렇다면 최단 경로 밖의 칸은 어떨까요? 미로 왼쪽 아래 구석 (4,0)을 봅시다. 여기까지 오는 가장 짧은 길은 8걸음입니다 — 왼쪽 벽 (2,0)·(2,1)·(3,0) 때문에 곧장 내려올 수 없어 2열까지 비켜 갔다가 내려온 뒤 다시 왼쪽으로 두 칸 돌아와야 하지요. 목표까지의 어림은 |4−6| + |0−11| = 2 + 11 = 13입니다. 그러니 f = 8 + 13 = 21. 17보다 4가 큽니다.

이 4의 차이가 뜻하는 바가 중요합니다. "이 칸을 거쳐 가면 아무리 잘해도 21걸음"이라는 선언이에요. 17걸음짜리 길이 있다는 것을 아는 순간, (4,0)은 볼 값어치가 없어집니다. f는 단순한 점수가 아니라 가지치기의 근거입니다.

2

규칙은 한 줄뿐이다 — 대기실에서 f가 가장 작은 칸을 꺼낸다

4차시에서 우리는 프론티어라는 낱말을 배웠습니다. "가 볼 수는 있는데 아직 안 가 본 칸"들이 모여 있는 대기실이지요. 탐색이란 결국 이 두 동작의 되풀이였습니다.

  • 대기실에서 한 칸을 꺼낸다.
  • 그 칸의 이웃들을 대기실에 넣는다.

여기서 알고리즘의 정체를 정하는 것은 오직 하나, 대기실에서 누구를 먼저 꺼내느냐입니다.

대기실의 규칙먼저 꺼내는 것이름이 미로에서
줄 서기(큐)가장 먼저 들어온 칸너비 우선(BFS) 64칸 · 17걸음
쌓기(스택)가장 나중에 들어온 칸깊이 우선(DFS) 22칸 · 19걸음
h가 작은 순목표에 가까워 보이는 칸탐욕적 탐색 20칸 · 19걸음
f가 작은 순f = g + h가 가장 작은 칸 A*오늘 잰다

A*의 규칙은 표의 마지막 줄이 전부입니다. 다시 한 문장으로 적으면 이렇습니다.

대기실에 있는 칸들 가운데 f = g + h가 가장 작은 칸을 꺼낸다.

더 있느냐고요? 없습니다. 정말 이것뿐입니다. 오늘 시뮬레이터에서 여러분이 할 일도 이 한 줄을 확인하는 것입니다 — 화면을 멈춰 세우고 "다음에 어느 칸이 뽑힐까?"를 직접 찍어 맞히는 것이지요. 찍을 때 필요한 정보는 오직 대기실 칸들의 f 값뿐입니다.

💡 왜 '가장 작은' 것인가

f는 길이이기 때문입니다. 길이는 짧을수록 좋지요. f가 12인 칸과 20인 칸이 대기실에 함께 있다면, 12쪽이 더 짧은 길로 이어질 가능성이 있는 후보입니다. 20쪽을 먼저 뒤지는 것은 짧은 후보를 놔두고 긴 후보부터 파는 셈이에요.

동점이 나면 어떻게 하나

여기서 학생들이 반드시 걸리는 자리가 있습니다. f가 같은 칸이 여럿이면 어떻게 할까요?

답은 "아무 쪽이나"입니다. 규칙은 '가장 작은 f'만 정할 뿐, 동점끼리의 순서는 정하지 않습니다. 실제 프로그램은 대기실을 만든 방식에 따라 어느 하나를 고르게 되는데, 그것은 알고리즘의 뜻이 아니라 만드는 방법의 부산물입니다. 어느 쪽을 골라도 찾아내는 길의 길이는 같습니다.

다만 둘러본 칸의 수는 달라질 수 있습니다. 그리고 이 미로에서는 동점이 아주 흔합니다. 앞 절에서 본 대로 최단 경로 위 칸은 전부 f = 17이니까요. 실제로 오늘의 A*를 돌리면, 한 걸음 나아갈 때마다 대기실에서 평균 3.8칸이 f 동점이고, 가장 많을 때는 6칸이 나란히 f = 17로 묶입니다. A*가 52칸이나 꺼내야 하는 까닭이 여기에 있습니다 — 17이라는 이름표를 단 칸을 전부 확인해야 끝나는 것이지요.

⚠️ 4차시의 64칸과 오늘의 65칸 — 이건 오류가 아니다

오늘 시뮬레이터에서 h를 아예 안 보게 만들면(뒤에 나오는 w = 0) 65칸이 나옵니다. 그런데 4차시 너비 우선 탐색은 64칸이었지요. 같은 미로에서 같은 17걸음을 찾는데 한 칸이 다릅니다. 왜일까요?

이 미로에서 시작점으로부터 거리가 17인 칸은 딱 둘입니다 — 목표 (6,11)과 그 왼쪽의 (6,9)입니다. 마지막 순간에 이 두 칸이 대기실에 나란히 남아 동점이 됩니다.

  • 너비 우선은 줄 선 차례대로 꺼내다가 목표를 먼저 뽑고 그 자리에서 끝냅니다. 그래서 (6,9)는 영영 꺼내지 못합니다 → 64칸.
  • 오늘의 방식은 f가 작은 순으로 꺼내는데, 동점 처리 순서상 (6,9)가 먼저 나옵니다. 그다음에 목표를 꺼내고 끝납니다 → 65칸.

경로는 둘 다 17걸음으로 똑같습니다. 한 칸의 차이는 알고리즘이 달라서가 아니라 동점을 어느 손으로 집었느냐의 차이입니다. 이런 자리를 그냥 넘어가면 "책이 틀렸다"고 생각하게 되니, 여기서 못 박아 둡니다.

3

저울의 양 끝 — h를 지우면 다익스트라, g를 지우면 탐욕적

f = g + h를 저울이라고 부른 까닭이 있습니다. 한쪽 접시를 비워 보면 이미 아는 알고리즘이 튀어나오기 때문입니다.

h = 0

다익스트라

남은 어림을 아예 안 본다. f = g가 되어 지나온 비용만 따진다. 목표가 어느 쪽인지 모르니 사방으로 둥글게 퍼진다.

f = g + h

A*

둘을 있는 그대로 더한다. 뒤와 앞을 함께 본다. 이 차시의 주인공.

g 무시

탐욕적 탐색

지나온 비용을 안 본다. f = h가 되어 목표 쪽으로만 쏜다. 5차시에서 이미 만났다.

왼쪽 끝부터 봅시다. h를 0으로 두면 f = g + 0 = g가 됩니다. 대기실에서 '지나온 비용이 가장 작은 칸'을 꺼낸다는 뜻이지요. 이것이 다익스트라 알고리즘입니다. 내비게이션의 뿌리이자, 지금도 지도 앱 안에서 돌고 있는 방법이에요.

강의 중인 에츠허르 다익스트라, 1994년
에츠허르 다익스트라(1930–2002). 그가 만든 최단 경로 알고리즘은 오늘 우리 식에서 h를 0으로 둔 자리에 정확히 놓입니다. A*는 다익스트라를 밀어낸 것이 아니라, 그 위에 나침반 하나를 얹은 것입니다. 출처: Andreas F. Borchert, Wikimedia Commons (CC BY-SA 4.0)

오른쪽 끝은 이미 만나 봤습니다. g를 무시하면 f = h가 되어 "목표에 가까워 보이는 칸"만 고릅니다. 5차시의 탐욕적 탐색이고, 이 미로에서 20칸 19걸음이었지요.

그리고 그 사이가 A*입니다. 세 결과를 미리 한 표에 놓겠습니다. 오늘 여러분이 시뮬레이터로 직접 재서 채울 표이기도 합니다.

보는 것이름둘러본 칸경로 길이최단인가
g만다익스트라65 17걸음O
g + hA*52 17걸음O
h만탐욕적 탐색20 19걸음X
빈칸 65칸짜리 같은 미로에서 잰 값. 최단은 17걸음입니다.

가운데 줄을 다시 보세요. A*는 다익스트라보다 13칸을 덜 보면서도 똑같이 17걸음을 찾았습니다. 아무것도 내주지 않고 20%를 아낀 것입니다. 이것은 운이 좋아서가 아니라 반드시 그렇게 되는 일입니다. 까닭은 한 줄로 설명됩니다.

h ≥ 0 이므로   f = g + h ≥ g

남은 어림 h는 거리이므로 절대 음수가 될 수 없습니다. 그러니 어떤 칸이든 f는 g보다 작아질 수 없습니다. 다익스트라가 "g가 17 이하인 칸"을 전부 꺼내는 동안, A*는 그중에서도 f까지 17 이하인 칸만 꺼냅니다. A*가 보는 칸은 언제나 다익스트라가 보는 칸의 일부인 것이지요.

숫자로 확인해 보면 더 분명합니다. 다익스트라가 꺼낸 65칸을 f 값으로 나누면 f = 17인 칸이 52개, f = 19인 칸이 10개, f = 21인 칸이 3개입니다. A*가 꺼낸 52칸은 그 f = 17짜리 52칸과 정확히 같은 집합이에요. 다익스트라가 더 본 13칸은 f가 19와 21인 칸들 — 앞 절에서 본 (4,0)처럼 애초에 최단이 될 수 없는 칸들입니다. A*는 그 13칸을 보지 않아도 된다는 것을 f 하나로 알아챈 것입니다.

💭 잠깐 생각해 보기

그러면 벽을 아무리 이상하게 세워도 A*가 다익스트라보다 많이 둘러보는 일은 영원히 없을까요? 위의 한 줄(f ≥ g)만 보면 그럴 것 같습니다. 다음 시간에 벽 하나를 옮기는 경우 58가지, 벽 둘을 옮기는 경우 1,647가지를 코드로 전부 돌려서 확인합니다. 답은 그때 확인하세요.

4

어림을 부풀리면 어디가 깨지는가 — 허용 가능성과 배율 w

A*가 최단을 보장한다고 했는데, 조건이 하나 붙습니다. 그 조건이 오늘의 마지막 개념입니다.

📐 A*가 최단을 보장하는 조건

남은 어림 h가 실제 남은 비용을 넘지 않는다.
이 성질을 허용 가능성(admissibility)이라고 부릅니다. "어림이 실제보다 크지 않다", 곧 절대 부풀리지 않는다는 뜻입니다.

우리가 쓰는 맨해튼 거리는 이 조건을 만족합니다. 왜냐하면 벽을 무시하고 재기 때문입니다. 벽이 없다면 딱 그만큼 걸으면 되고, 벽이 있으면 돌아가야 하니 실제로는 그보다 더 걸립니다. 그러니 맨해튼 거리는 언제나 실제 남은 걸음 수보다 작거나 같습니다. 실수로 크게 잡는 일이 없어요.

그렇다면 이렇게 물어볼 수 있습니다. 일부러 부풀리면 무슨 일이 벌어질까? 확인하는 방법은 간단합니다. h에 배율 w를 곱하는 것이지요.

f = g + w × h

이 눈금 하나로 저울의 왼쪽 끝부터 오른쪽 끝까지 이어서 움직일 수 있습니다.

  • w = 0 — h가 통째로 사라져 다익스트라가 됩니다.
  • w = 1 — 있는 그대로 더하는 A*입니다. 허용 가능성이 지켜집니다.
  • w > 1 — 남은 거리를 실제보다 멀다고 거짓말합니다. 허용 가능성이 깨질 수 있습니다.

부풀리면 왜 최단이 깨질까요? 그림을 그려 보면 이렇습니다. A*가 두 후보 앞에 서 있다고 합시다. 하나는 돌아가는 것처럼 보이지만 실제로는 최단인 길이고, 다른 하나는 목표를 향해 곧장 가지만 조금 뒤에 막히는 길입니다. 제대로 된 h라면 두 후보의 f가 비슷하게 나와서, A*는 둘 다 확인해 봅니다. 그런데 h를 3배로 부풀리면 '남았다'는 쪽의 무게가 3배가 됩니다. 돌아가는 길은 남은 거리가 조금 더 크므로 f가 훨씬 커 보이고, A*는 그 길을 확인하기도 전에 밀어내 버립니다.

실제로 이 미로에서 그렇게 됩니다. 배율을 크게 올리면 A*는 오른쪽 세로 통로에서 (2,10) 다음에 (2,11)로 새어 나갔다가 (3,11)·(4,11)을 거쳐 다시 (4,10)으로 돌아옵니다. 딱 2걸음을 손해 보고 19걸음이 되지요. 5차시 탐욕적 탐색이 걸었던 바로 그 길입니다.

그런데 여기서 실제로 재 보면 예상 밖의 일이 하나 나옵니다. "부풀리면 빨라지는 대신 최단이 깨진다"는 맞바꿈이라면, 빨라지는 지점과 깨지는 지점이 같아야 할 것 같습니다. 그렇지 않습니다.

0 1 2 3 4 5 w 65 → 52칸 17걸음 · 최단 21칸 17걸음 · 최단 20칸 19걸음 · 최단 아님 w = 1.1 속도가 꺾이는 문턱 w = 3.1 최단이 깨지는 문턱 ↑ 다익스트라 ↑ A* 이 구간은 2.5배 빨라지면서 최단도 지킨다 — 공짜다

그림 2. 배율 w를 0.0부터 0.1씩 올리며 잰 결과. 문턱이 두 개이고, 그 사이가 2.0만큼 벌어져 있습니다. 이 두 값은 오늘 여러분이 직접 찾습니다.

그림 2가 말하는 것을 정리하면 이렇습니다.

  • 속도가 꺾이는 문턱은 w = 1.1입니다. 여기서 둘러본 칸이 52칸에서 21칸으로 단번에 2.5배 줄어듭니다. 그런데 경로는 여전히 17걸음, 최단 그대로입니다.
  • 최단이 깨지는 문턱은 w = 3.1입니다. 여기서 처음으로 경로가 17걸음에서 19걸음으로 늘어납니다. 둘러본 칸은 21칸에서 20칸으로 겨우 1칸 줄 뿐입니다.
  • 따라서 w가 1.1에서 3.0 사이인 구간은 손해가 없습니다. 2.5배 빨라지면서 최단도 지킵니다. 맞바꿈이 아니라 그냥 이득이에요.

1.1에서 왜 그렇게 크게 떨어질까요? 개념 2의 동점이 답입니다. w = 1일 때는 최단 경로 위 칸이 전부 f = 17로 묶여 있어서 A*가 그 52칸을 다 확인해야 했습니다. 배율을 조금만 올리면 h가 큰 칸이 더 크게 밀려나 동점이 풀립니다. 그러면 A*는 목표에 가까운 쪽부터 골라 21칸만 보고 끝냅니다. w가 하는 일의 절반은 동점을 깨는 것입니다. 오늘 시뮬레이터에는 대기실의 동점이 몇 칸인지 세어 주는 칸이 있으니, w를 1.0과 1.1로 두고 그 숫자가 어떻게 달라지는지 눈으로 보세요.

⚠️ 흔한 오해

"w를 1보다 크게 하면 곧바로 최단이 깨진다"고 생각하기 쉽습니다. 이 미로에서는 3.0까지 멀쩡합니다. 허용 가능성은 최단을 보장하는 충분한 조건이지 반드시 필요한 조건은 아닙니다. 곧 "부풀리면 깨질 수도 있다"이지 "부풀리면 반드시 깨진다"가 아니에요. 어디서 깨지는지는 미로가 정합니다. 벽을 바꾸면 3.1도 달라집니다. 그래서 이런 값은 재 봐야 압니다.

이름의 별표는 무슨 뜻인가

A*의 별표(*)는 장식이 아닙니다. "이 방법이 최적임이 증명되었다"는 표시입니다. 허용 가능한 h를 쓰는 한 A*는 최단을 반드시 찾고, 게다가 같은 어림을 가진 어떤 방법도 A*보다 적게 둘러볼 수 없다는 것까지 증명되어 있습니다. 오늘 배운 덧셈 한 줄이 그런 자리를 차지하고 있는 것이지요.

강당에서 나이 지긋한 연구자 열 명 남짓이 IEEE 이정표 동판을 가운데 두고 나란히 서 있는 모습. 동판 제목은 'SHAKEY: The World's First Mobile Intelligent Robot, 1972'이다
5차시 끝에서 만난 로봇 셰이키를 만든 SRI 연구진이 2017년 2월 컴퓨터 역사 박물관에 다시 모였습니다. 가운데 동판은 IEEE가 셰이키를 '세계 최초의 이동 지능 로봇'으로 기려 세운 것으로, 셰이키의 길 찾기와 계획 방법이 로봇 연구, 그리고 웹 서버·자동차·공장·비디오 게임·화성 탐사 로봇의 설계로 이어졌다고 적혀 있습니다. 5차시에 "어림 h는 A*의 절반"이라고 했지요 — 나머지 절반이 g였고, 둘을 잇는 것이 덧셈이었습니다. 출처: Dougfairbairn, Wikimedia Commons (CC BY-SA 4.0)

셰이키에게 걸린 요구는 두 가지였고, 서로 반대 방향이었습니다. 하나는 "적게 봐라" — 그때의 컴퓨터로 방 안의 모든 길을 다 따지면 로봇이 한참을 멈춰 서 있어야 했으니까요. 다른 하나는 "옳은 길을 내라" — 상자를 밀어야 하는 로봇이 헛걸음을 하면 일이 안 됩니다. 4차시의 너비 우선은 앞의 요구를 못 채웠고, 5차시의 탐욕적 탐색은 뒤의 요구를 못 채웠습니다. 두 요구를 동시에 채운 것이 f = g + h이고, 그래서 별표가 붙었습니다. 이론이 먼저가 아니라 멈춰 선 로봇이 먼저였던 셈입니다.

💻

손으로 — 세워 놓고 다음 칸을 맞히고, 문턱을 찾는다

아래 시뮬레이터는 지금까지 이야기한 미로 그대로입니다. 칸마다 왼쪽 위에 g, 오른쪽 위에 h, 가운데 큰 글씨로 f가 찍힙니다. 한 걸음씩 세울 수 있고, 세워 둔 채로 다음에 어느 칸이 뽑힐지 직접 찍어 볼 수 있습니다. 오늘의 15분은 아래 네 과제입니다. 공책을 펴 두세요. 적지 않으면 확인 문제를 못 풉니다.

  • 세 방식을 돌려 표를 채운다. 방식을 다익스트라 → A* → 탐욕적으로 바꿔 가며 ⏩ 끝까지를 누르고, 둘러본 칸 · 경로 길이 · 최단인가를 아래 표에 적습니다.
  • 다음 칸을 맞힌다. 🎯 맞히기 켜기를 누르면 화면이 멈춥니다. 대기실(파란 테두리) 칸들의 f를 눈으로 훑어 가장 작은 f를 가진 칸을 클릭하세요. 세 번 연속 맞히면 통과입니다.
  • 문턱 두 개를 찾는다. 방식을 A*로 두고 h 배율 슬라이더를 0.1씩 올립니다. 그리고 두 값을 찾아 적습니다 — ⓐ 둘러본 칸이 크게 줄어드는 첫 배율, ⓑ 경로가 17걸음에서 늘어나는 첫 배율. 둘은 같은 값이 아닙니다.
  • 슬라이더를 0.0까지 내린다. 화면이 다익스트라와 똑같아지는지 확인합니다. 숫자 하나까지 같아야 합니다.
🧭 A* 시뮬레이터 — 칸마다 g · h · f INTERACTIVE

보라색 = 이미 꺼낸 칸, 파란 테두리 = 대기실에 있는 칸, 노란 테두리 = 방금 꺼낸 칸, 초록 = 찾아낸 경로. 칸 안의 숫자는 왼쪽 위 g, 오른쪽 위 h, 가운데 f입니다. f는 실제로 대기실 순서를 정하는 값이라 배율 w를 올리면 가운데 숫자가 같이 커집니다. 탐욕적 방식에서는 g를 안 보므로 가운데 숫자가 곧 h입니다. 방식 칸에서 A*를 고르면 배율이 1.0으로, 다익스트라를 고르면 0.0으로 돌아갑니다.

꺼낸 칸 대기실 방금 꺼낸 칸 찾아낸 경로 벽
1.0
방식A* (w=1.0)
둘러본 칸0
대기실1
최소 f 동점1
방금 꺼낸 칸—
경로—
연속 정답0
🎉 세 번 연속 맞혔습니다 — 통과! 여러분은 지금 A*의 규칙 한 줄을 계산해서 쓴 것입니다.
[안내] ▶ 재생을 누르거나 ⏭ 한 걸음으로 시작하세요.

과제 ① 세 방식 표 채우기

방식을 바꾸면 화면이 저절로 초기화됩니다. ⏩ 끝까지를 눌러 결과를 얻고 아래에 적으세요. 최단은 17걸음이라는 것만 알고 시작합니다.

방식둘러본 칸경로 길이최단인가 (O/X)
다익스트라 (g만)
A* (g + h, w = 1)
탐욕적 (h만)
💡 표를 채우고 나서 볼 것

세 줄 중에서 둘러본 칸이 가장 적은 줄과 경로가 가장 짧은 줄을 각각 찾아 동그라미 치세요. 같은 줄인가요, 다른 줄인가요? 이 물음이 오늘 확인 문제 3번입니다.

과제 ② 다음 칸 맞히기

🎯 맞히기 켜기를 누르면 재생이 멈추고 클릭을 기다립니다. 대기실에 있는 칸(파란 테두리) 중에서 f가 가장 작은 칸을 클릭하세요. 동점이 여럿이면 그중 아무거나 맞습니다 — 규칙이 정하는 것은 '가장 작은 f'뿐이니까요.

  • 맞히면 그 칸이 실제로 꺼내지고 연속 정답이 1 올라갑니다.
  • 틀리면 정답 칸에 초록 동그라미가 표시되고 연속 정답이 0으로 돌아갑니다. 정답을 확인한 뒤 ⏭ 한 걸음으로 넘어갑니다.
  • 세 번 연속 맞히면 통과 표시가 뜹니다.
⚠️ 처음 몇 걸음은 너무 쉽다

출발 직후에는 대기실에 후보가 한 칸밖에 없어 고를 것이 없습니다. 그럴 때는 시뮬레이터가 알아서 한 걸음 넘기고 그 사실을 기록 창에 적습니다. 후보가 둘 이상일 때부터가 진짜 문제예요. 재미가 없으면 ⏭ 한 걸음으로 열 걸음쯤 진행한 뒤 맞히기를 켜 보세요 — 대기실이 커질수록 어려워집니다.

과제 ③ 문턱 두 개 찾기

방식을 A*로 두고 슬라이더를 0.1씩 올리며 ⏩ 끝까지를 반복합니다. 아래 값들부터 재 보세요.

w둘러본 칸경로 길이 w둘러본 칸경로 길이
0.0 2.0
0.5 3.0
1.0 3.1
1.1 5.0
찾아야 하는 값내가 찾은 w그때 무엇이 달라졌나
ⓐ 둘러본 칸이 크게 줄어드는 첫 배율
ⓑ 경로가 17걸음에서 늘어나는 첫 배율
💭 재면서 생각할 것

ⓐ와 ⓑ 사이의 배율에서는 무슨 일이 벌어지고 있나요? 그 구간에서 A*는 무엇을 잃고 무엇을 얻나요? "빨라지려면 최단을 내놔야 한다"는 말이 이 미로에서 정확한 설명인지 판단해 보세요.

과제 ④ 슬라이더를 0.0으로

방식이 A*인 상태에서 슬라이더를 0.0까지 내려 보세요. 내리는 순간 방식 칸의 이름이 저절로 다익스트라로 바뀝니다. 화면이 이름을 바꿔 버리는 까닭은 둘이 같은 것이기 때문입니다. 그대로 ⏩ 끝까지를 눌러, 과제 ①에서 다익스트라 줄에 적어 둔 값과 숫자 하나까지 같은지 맞춰 보세요. 같다면 그것은 다익스트라가 A*의 특별한 경우라는 뜻입니다. 화면에서 h 칸이 여전히 숫자를 보여 주더라도, w = 0이 곱해지는 순간 f는 g와 같아집니다.

과제 ① — 다익스트라 65칸 · 17걸음 · O / A* 52칸 · 17걸음 · O / 탐욕적 20칸 · 19걸음 · X.

둘러본 칸이 가장 적은 줄은 탐욕적이고, 경로가 가장 짧은 줄은 다익스트라와 A*입니다. 같은 줄이 아니지요. 그런데 A*는 두 항목에서 모두 2등 안에 듭니다 — 최단을 지키면서 다익스트라보다 13칸을 아꼈으니까요.

과제 ③ — 잰 값은 이렇습니다.

w둘러본 칸경로w둘러본 칸경로
0.06517걸음 2.02117걸음
0.56417걸음 3.02117걸음
1.05217걸음 3.12019걸음
1.12117걸음 5.02019걸음

ⓐ w = 1.1에서 52칸이 21칸으로 떨어집니다(2.5배). 경로는 17걸음 그대로입니다.
ⓑ w = 3.1에서 경로가 17걸음에서 19걸음으로 늘어납니다. 둘러본 칸은 21에서 20으로 1칸만 줄어요.

그 사이 구간(1.1 ~ 3.0)에서는 2.5배 빨라지면서 최단도 지킵니다. 잃는 것이 없습니다. 그러니 "빨라지려면 최단을 내놔야 한다"는 이 미로에서는 틀린 설명입니다. 정확히 말하면 문턱이 두 개이고, 그 사이에는 공짜 구간이 있다입니다.

또 하나 눈여겨볼 것 — w = 3.1부터 5.0까지는 결과가 전혀 바뀌지 않습니다. 20칸 19걸음에서 멈춰 있어요. 이 값은 탐욕적 탐색과 정확히 같습니다. h를 3.1배 이상 부풀린 A*는 이 미로에서 사실상 탐욕적 탐색이 된 것입니다.

과제 ④ — A*에 w = 0.0과 다익스트라는 65칸 · 17걸음으로 완전히 같습니다. 꺼내는 순서까지 같아요. h에 0을 곱하면 f = g + 0 = g이니 당연한 결과입니다. "다익스트라는 h를 안 쓰는 A*"라는 문장을 화면으로 확인한 셈입니다.

📖

정리 — 덧셈 하나가 저울이 되었다

오늘 배운 것은 식 하나였습니다. f = g + h. 그런데 이 짧은 식이 지금까지 배운 탐색을 전부 한 줄에 꿰어 놓았습니다.

무엇을 보는가이름둘러본 칸경로최단한 줄 평
f = g다익스트라65 17걸음O정직하지만 다 본다
f = g + hA*52 17걸음O공짜로 13칸을 아꼈다
f = g + 2h부풀린 A*21 17걸음O2.5배 빠른데도 최단
f = g + 5h많이 부풀린 A*20 19걸음X1칸 아끼고 2걸음 잃었다
f = h탐욕적 탐색20 19걸음X맨 오른쪽 끝
다섯 줄이 전부 같은 함수에 숫자 하나만 바꿔 나온 결과입니다.

표의 아래 두 줄을 견주어 보세요. 많이 부풀린 A*와 탐욕적 탐색은 숫자가 똑같습니다. 우연이 아니라, h를 충분히 부풀리면 g가 사실상 무시되기 때문입니다. 저울의 오른쪽 끝에 도착한 것이지요.

오늘 기억할 것을 세 줄로 줄이면 이렇습니다.

  • 규칙은 한 줄이다. 대기실에서 f = g + h가 가장 작은 칸을 꺼낸다. g는 뒤를 돌아본 값, h는 앞을 내다본 값이다.
  • h를 어떻게 다루느냐가 저울의 눈금이다. h를 0으로 두면 다익스트라, g를 버리면 탐욕적, 있는 그대로 더하면 A*.
  • 부풀리면 최단이 깨질 수 있다. 다만 언제 깨지는지는 미로가 정하므로 재 봐야 안다. 이 미로에서는 1.1과 3.1, 문턱이 두 개였다.
📖 다음 시간에는

오늘은 남이 만들어 둔 화면의 버튼을 눌렀습니다. 다음 7차시에는 그 화면을 지우고 같은 것을 직접 코드로 짭니다. 4차시 너비 우선 탐색 코드에서 바뀌는 곳은 두 군데뿐이에요 — 대기실을 무엇으로 쓰느냐, 그리고 꺼내는 순서를 무엇으로 정하느냐. 오늘 슬라이더로 찾은 1.1과 3.1을 코드로 다시 재서, 여러분이 눈으로 본 값과 같은지 맞춰 볼 것입니다.

🔁 되돌아보기

오늘 g와 h를 더해 한 저울에 올리는 법을 배우고, 슬라이더를 밀어 최단이 깨지는 문턱을 직접 찾았습니다. 공책을 덮기 전에 한 줄만 적으세요 — "오늘 가장 뜻밖이었던 숫자 하나와, 왜 뜻밖이었는지." (예: "3.0까지 최단이 유지된 것 — 1을 넘기면 바로 깨질 줄 알았는데") 다음 시간에는 이것을 코드로 다시 확인합니다.

✅

확인 문제

✍️ 문제마다 답을 쓰고 제출하기를 누르세요. 제출하면 모범 답안이 열리고, 제출한 답은 선생님께 전달됩니다.

1. g, h, f가 각각 무엇인지 한 줄씩 쓰고, A*가 다음에 볼 칸을 고르는 규칙을 한 문장으로 쓰시오.
📖 모범 답안

g — 지나온 비용. 시작점에서 그 칸까지 실제로 걸은 걸음 수. 이미 지나온 길이라 어림이 아니라 확정된 값이다.
h — 남은 어림. 그 칸에서 목표까지 남았다고 짐작한 걸음 수. 우리 미로에서는 벽을 무시하고 잰 맨해튼 거리를 쓴다.
f = g + h — 그 칸을 거쳐 가는 길 전체의 길이 어림.

규칙: 대기실(프론티어)에 있는 칸 가운데 f가 가장 작은 칸을 먼저 꺼낸다. f가 같은 칸이 여럿이면 그중 아무 칸이나 꺼내도 되며, 찾아내는 길의 길이는 달라지지 않는다.

2. h를 0으로 두면 A*가 어떤 알고리즘이 되는지, g를 무시하면 어떤 알고리즘이 되는지 이름과 함께 답하고, 오늘 시뮬레이터에서 두 경우가 각각 몇 칸을 둘러보고 몇 걸음짜리 길을 냈는지 쓰시오.
📖 모범 답안

h = 0 → 다익스트라 알고리즘. f = g + 0 = g가 되어 지나온 비용만 본다. 이 미로에서 65칸 · 17걸음이고 최단이다. 목표가 어디인지 모르니 사방으로 고르게 퍼져 빈칸 65칸을 전부 꺼내게 된다.

g 무시 → 탐욕적 탐색. f = h가 되어 목표에 가까워 보이는 칸만 고른다. 이 미로에서 20칸 · 19걸음이고 최단이 아니다.

두 경우가 저울의 양 끝이고, A*(52칸 · 17걸음)는 그 사이에 있다. 까닭까지 붙이면: 다익스트라는 앞을 안 봐서 많이 보고, 탐욕적은 뒤를 안 봐서 돌아온 길의 손해를 못 셈한다.

3. 과제 ①에서 채운 표를 보시오. 탐욕적 탐색이 A*보다 적게 둘러본 경우가 있었는가? 있었다면 그 숫자를 쓰고, 그것이 A*의 패배가 아닌 까닭을 설명하시오. (오늘 직접 잰 값을 쓸 것)
📖 모범 답안

있었다. 탐욕적 20칸 vs A* 52칸 — 탐욕적이 A*보다 32칸이나 적게 둘러보았다. 둘러본 칸만 놓고 보면 탐욕적의 압승이다.

그러나 A*의 패배가 아니다. 두 방식이 내놓은 답이 다르기 때문이다. 탐욕적이 낸 길은 19걸음이고 A*가 낸 길은 17걸음이다. 둘은 같은 문제를 푼 것이 아니라, 하나는 '괜찮은 답'을, 다른 하나는 '최선의 답'을 낸 것이다. 둘러본 칸 수만으로 순위를 매기는 것은 답의 질을 공짜로 친다는 뜻이고, 그것은 비교가 아니다.

덧붙여 — 이 '20칸'이라는 이점이 답의 질을 대신하지는 못한다는 것을 5차시에서 이미 봤다. 그때 만든 'ㄷ자 함정' 미로에서 탐욕적 탐색은 41칸 · 29걸음, 너비 우선은 63칸 · 17걸음이었다. 둘러본 칸이 적다는 이점은 그 미로에서도 그대로였지만, 치른 값은 2걸음에서 12걸음으로 여섯 배가 되었다. 아끼는 칸 수는 대체로 남고 손해의 크기는 미로가 정한다 — 그래서 재 봐야 안다.

4. 과제 ③에서 찾은 ⓐ 둘러본 칸이 크게 줄어드는 첫 배율과 ⓑ 경로가 길어지는 첫 배율을 각각 쓰고, 두 값이 왜 서로 다른 자리에 있는지 설명하시오. (오늘 직접 잰 값을 쓸 것)
📖 모범 답안

ⓐ w = 1.1 — 둘러본 칸이 52칸에서 21칸으로 떨어진다(2.5배). 경로는 17걸음 그대로.
ⓑ w = 3.1 — 경로가 17걸음에서 19걸음으로 늘어난다. 둘러본 칸은 21에서 20으로 1칸만 준다.

왜 다른 자리인가. 두 문턱이 하는 일이 다르기 때문이다.

ⓐ에서 일어나는 일은 동점 깨기다. w = 1일 때 이 미로의 최단 경로 위 칸은 전부 f = 17로 묶여 있어서, A*는 그 52칸을 다 확인해야 끝났다. 배율을 조금만 올리면 h가 큰 칸이 더 크게 밀려나 동점이 풀리고, A*는 목표에 가까운 쪽부터 21칸만 보고 끝낸다. 이때는 최단 경로가 여전히 f가 가장 작으므로 답이 안 바뀐다.

ⓑ에서 일어나는 일은 순서 뒤집기다. 부풀림이 충분히 커지면 최단 경로 위의 칸이 돌아가는 것처럼 보여 다른 후보보다 f가 커진다. 그러면 A*는 최단 경로를 확인해 보기도 전에 목표에 닿아 버린다. 여기서 답이 바뀐다.

그래서 1.1에서 3.0 사이는 손해 없는 구간이다. "빨라지려면 최단을 내놔야 한다"는 설명은 이 미로에서는 맞지 않는다.

5. 대기실에 두 칸이 있다. 하나는 g = 4, h = 3이고 다른 하나는 g = 1, h = 5다. A*가 먼저 보는 칸을 고르고 까닭을 쓰시오. 그리고 이 물음을 탐욕적 탐색과 다익스트라에게 각각 물으면 답이 어떻게 달라지는지도 쓰시오.
📖 모범 답안

A*는 뒤엣것(g = 1, h = 5)을 먼저 본다. f를 계산하면 앞엣것은 4 + 3 = 7, 뒤엣것은 1 + 5 = 6이다. A*는 f가 작은 쪽을 먼저 꺼내므로 6인 칸이 먼저다. "이 칸을 거쳐 가면 대략 6걸음짜리 길이 될 것 같다"는 쪽이 더 유망한 후보이기 때문이다.

탐욕적 탐색은 앞엣것(h = 3)을 먼저 본다. h만 보므로 3 < 5다. 지나온 4걸음은 눈에 들어오지 않는다.
다익스트라도 뒤엣것(g = 1)을 먼저 본다. g만 보므로 1 < 4다. 남은 5걸음은 눈에 들어오지 않는다.

세 방식이 같은 두 칸을 놓고 서로 다른 답을 낸다는 것이 오늘 배운 저울의 요점이다. 우연히 A*와 다익스트라의 답이 같아졌지만, 근거는 전혀 다르다.

6. 다음 중 A*로 풀기에 가장 어색한 문제를 고르고, 무엇이 없어서 어색한지 설명하시오. 나머지 셋에 대해서는 g와 h가 각각 무엇이 되는지 한 줄씩 쓰시오.
① 미로 탈출   ② 로봇청소기의 충전기 복귀 경로   ③ 8-퍼즐 최소 이동   ④ 오늘 점심 메뉴 정하기
📖 모범 답안

④ 오늘 점심 메뉴 정하기가 가장 어색하다.

A*가 돌아가려면 세 가지가 있어야 한다 — 비용(한 걸음에 얼마가 드는가), 목표(어디에 닿으면 끝인가), 그리고 어림 h(목표까지 얼마나 남았는가). 점심 메뉴 정하기에는 셋이 다 없다. '짜장면에서 김치찌개까지의 거리'라는 것이 무엇인지 말할 수 없고, '목표에 도착했다'를 판정할 기준도 없다. 애초에 경로를 찾는 문제가 아니라 하나를 고르는 문제다. 무리해서 점수를 매기더라도 그것은 A*가 아니라 다른 방법(예: 조건에 맞는 후보 고르기)이다.

나머지 셋 —

  • ① 미로 탈출 · g = 시작점에서 그 칸까지 걸은 걸음 수, h = 그 칸에서 출구까지의 맨해튼 거리.
  • ② 로봇청소기 복귀 · g = 지금까지 이동한 실제 거리(또는 쓴 전력), h = 지금 위치에서 충전기까지의 직선거리.
  • ③ 8-퍼즐 · g = 지금까지 조각을 민 횟수, h = 제자리에 없는 조각의 수, 또는 각 조각이 제자리까지 가야 하는 거리의 합. 다음 8차시에 이 h를 두 가지로 만들어 직접 견줍니다.

정리하면, A*는 '상태에서 상태로 옮기는 데 비용이 들고, 목표가 정해져 있고, 남은 비용을 어림할 수 있는' 문제에 쓴다. 셋 중 하나라도 없으면 A*의 문제가 아니다.

🔎

더 알아보기

오늘의 h가 어디서 왔고, 부풀린 A*와 지도 앱은 실제로 어떻게 쓰이나

옛 손그림 지도 일부. 가로로 넓게 뻗은 AVENUE A·B·C·D를 세로로 촘촘한 좁은 길들이 잘라 바둑판 모양의 블록을 이루고, 오른쪽 아래는 강물이다
원리 더 깊이

맨해튼 거리 — 바둑판 도시에서 온 이름

사진은 1811년에 확정된 뉴욕 맨해튼의 도시 계획 지도 일부입니다. 아직 들판이던 땅 위에 곧은 길을 바둑판처럼 미리 그어 놓았지요. 이 도판에서는 넓은 AVENUE A·B·C·D가 가로로 나 있고, 그 사이를 좁은 길(스트리트)이 세로로 촘촘히 자릅니다(지도가 옆으로 눕혀 그려져 있어요). 이런 도시에서는 건물을 뚫고 질러갈 수 없으니, 두 곳 사이의 실제 거리는 가로로 간 거리 + 세로로 간 거리입니다. 그래서 이 거리 재기를 맨해튼 거리, 또는 택시가 달리는 거리라는 뜻에서 택시 거리라고 부릅니다.

우리 미로도 위·아래·왼쪽·오른쪽으로만 한 칸씩 움직이니 사정이 같습니다. |행 차이| + |열 차이|는 벽이 하나도 없을 때 정확한 걸음 수이고, 벽이 있으면 돌아가야 하니 실제 걸음 수는 그보다 크거나 같습니다. 이 '작거나 같다'가 곧 허용 가능성이고, 오늘 A*가 최단을 지킨 근거가 여기서 나옵니다.

그런데 대각선 이동을 한 걸음으로 허용하면 이야기가 달라집니다. 대각선으로 한 걸음이면 닿는 칸을 맨해튼 거리는 2로 셉니다 — 실제보다 크게 어림하니 허용 가능성이 깨지지요. 그때는 두 차이 중 큰 쪽만 세는 체비쇼프 거리나 곧은 선 길이인 유클리드 거리처럼 실제를 넘지 않는 다른 자를 씁니다. 움직이는 규칙이 바뀌면 h도 따라 바뀌어야 합니다.

사진: 1811년 맨해튼 도시 계획 지도(알파벳 애비뉴 일대) · 출처: William Bridges, -1814 Peter Maverick, 1780-1831, Wikimedia Commons (Public domain)

경로 길이 — 보장된 상한과 실제로 잰 값 17 85 123 45 h 배율 w 보장: 길이 ≤ w × 17 실제로 잰 길이: 17 → 19 (w = 3.1부터) 보장이 허락했지만 쓰이지 않은 여유
현장

게임은 왜 일부러 부풀린 A*를 쓸까 — 손해에는 상한이 있다

실시간 전략 게임에서는 유닛 수백 기가 동시에 길을 찾습니다. 한 기가 최단을 얻으려고 52칸을 뒤지면 200기면 10,400칸이에요. 화면은 1초에도 수십 번 다시 그려야 하니 그 짧은 틈에 계산이 끝나야 합니다. 그래서 게임의 길 찾기에서는 h에 1보다 큰 배율을 곱해 둘러보는 칸을 줄이는 가중 A*(weighted A*)가 흔히 쓰입니다. h에 무게를 더 싣는 이 방식은 1970년 무렵 아이라 폴(Ira Pohl)이 연구했습니다.

부풀리면 최단이 깨질 수 있다고 했지요. 그런데 얼마나 깨지는지에는 한계가 있습니다. 원래의 h가 허용 가능하다면, 배율 w를 곱한 A*가 내놓는 길은 최단의 w배를 넘지 않는다는 것이 증명되어 있습니다. w = 1.5라면 아무리 운이 나빠도 최단보다 50% 넘게 길어지지 않는다는 약속이에요.

그림은 이 약속을 오늘 미로에 겹쳐 본 것입니다. w = 5에서 보장은 85걸음까지 허락하지만 실제로 잰 길이는 19걸음이었습니다. 약속은 가장 나쁜 경우를 묶어 둘 뿐이고 실제 손해는 대개 훨씬 작습니다. 그래서 "최적이 꼭 필요하지 않은 곳에서는 최적을 사지 않는다"는 판단이 가능하고, 반대로 한 걸음이 비싼 곳이라면 w를 1로 두어 최단을 지키면 됩니다. 눈금을 어디에 둘지는 문제의 값어치가 정합니다.

한쪽에서만 퍼지기 양쪽에서 퍼져 만나기 출발 도착 출발 도착 만나는 곳 큰 원 하나 반지름 절반인 원 둘 원의 넓이는 반지름²에 비례 → 훑는 넓이가 대략 절반
현장

내비게이션은 정말 다익스트라를 쓸까 — 양쪽에서 파고, 큰길부터 본다

다익스트라는 지도 길 찾기의 뿌리지만, 오늘날의 지도 앱이 그대로 쓰지는 않습니다. 전국 도로망은 교차로가 수백만 개라 사방으로 고르게 퍼지면 서울에서 부산을 찾는 동안 강원도와 전라도까지 훑게 됩니다. 오늘 배운 h를 더하면 탐색이 목표 쪽으로 기울지만, 실제 서비스는 여기에 몇 가지를 더 얹습니다.

하나는 그림의 양방향 탐색입니다. 출발지와 도착지에서 동시에 퍼져 나가 가운데서 만나게 하지요. 한쪽에서만 퍼지면 반지름이 두 곳 사이 거리만 한 원을 훑어야 하지만, 양쪽에서 퍼지면 반지름이 그 절반인 원 두 개면 됩니다. 원의 넓이는 반지름의 제곱에 비례하므로 훑는 넓이가 대략 절반으로 줄어듭니다.

다른 하나는 도로에 등급을 매기는 것입니다. 먼 길을 갈 때 사람도 골목보다 고속도로를 먼저 떠올리듯, 미리 계산해 둔 '큰길 지도'를 먼저 보고 골목은 출발지와 도착지 근처에서만 봅니다. 그래도 뼈대는 오늘 그대로예요 — 대기실에서 가장 유망한 후보를 꺼낸다. 9차시에서는 여기에 잔디·모래·물처럼 길마다 다른 비용을 넣어 '거리가 아니라 시간을 최소로 하는' 문제를 다룹니다.