문제 보기 · Level 3 · 2021 KAKAO BLIND RECRUITMENT · 정답률 43% · 푼 사람 13,289명 (2026-09-30 기준)1
문제
지점 n개와 지점 사이 택시 요금(양방향)이 주어진다. A와 B가 s에서 함께 출발해 각자 a, b로 간다. 어느 지점까지 합승하고 거기서 따로 가도 되고, 처음부터 따로 가도 된다. 두 사람 요금 합의 최솟값을 돌려준다.
- 3 ≤ n ≤ 200, s, a, b는 서로 다르다
- 요금 1 ~ 100,000, 두 지점 사이 요금은 하나만 주어진다
- s에서 a, b로 가는 길은 늘 있다
풀이
막히면 한 단계씩 펼친다.
필요한 개념
플로이드–워셜: 갈라지는 지점 k를 모두 해 보려면 s → k, k → a, k → b의 최단 요금이 필요하다. 지점이 200개 이하라 모든 쌍의 최단 요금표를 한 번에 만든다.
1단계 · 작은 예로 손으로 풀기
합승은 이런 모양이다: s에서 k까지 함께 타고(요금 한 번), k에서 A는 a로, B는 b로 따로 간다. 그래서 요금 합은
(s → k 요금) + (k → a 요금) + (k → b 요금)
이다. k = s면 처음부터 따로 가는 것이다. 모든 k 중 가장 작은 값이 답이다. 각 부분은 당연히 최단 요금으로 가야 한다.
예시 1에서 k = 5면 s(4) → 1 → 5가 34원, 5 → 6이 2원, 5 → 3 → 2가 46원으로 합이 82원이다.
2단계 · 가장 단순한 방법과 그 속도
A의 길과 B의 길을 모두 짝지어 보면 길의 수가 폭발한다. 1단계처럼 “갈라지는 지점 k”만 고르면 k는 200가지뿐이다. 필요한 것은 최단 요금 세 가지를 빨리 아는 것이다.
3단계 · 핵심 아이디어
- 모든 쌍의 최단 요금표: 플로이드–워셜로 D[i][j]를 한 번 만든다. n = 200이면 800만 번이다.
- 갈라지는 지점을 모두 해 보기: 답은 모든 k에 대한 D[s][k] + D[k][a] + D[k][b]의 최솟값이다. 요금이 양방향이라 D[k][a] = D[a][k]다.
- 다른 방법: s, a, b에서 다익스트라를 한 번씩 돌려도 같은 세 값을 얻는다. 요금이 양방향이라 “k에서 a까지”는 “a에서 k까지”와 같기 때문이다. 점과 간선이 많을 때는 이쪽이 빠르다.
4단계 · 코드 흐름
- (n + 1)×(n + 1) 표를 무한대로 채우고 D[i][i] = 0, 요금을 양쪽에 적는다.
- 플로이드–워셜을 돌린다.
- k = 1 ~ n에서 D[s][k] + D[k][a] + D[k][b]의 최솟값을 돌려준다.
5단계 · 파이썬 코드
def solution(n, s, a, b, fares):
INF = float("inf")
D = [[INF] * (n + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
D[i][i] = 0
for c, d, f in fares:
D[c][d] = D[d][c] = f # 양방향
for k in range(1, n + 1): # 거쳐 가도 되는 지점을 늘린다
for i in range(1, n + 1):
for j in range(1, n + 1):
if D[i][k] + D[k][j] < D[i][j]:
D[i][j] = D[i][k] + D[k][j]
return min(D[s][k] + D[k][a] + D[k][b] for k in range(1, n + 1))
D[c][d] = D[d][c] = f: 두 칸에 같은 값을 한 줄로 넣는다.- 효율성 테스트가 빠듯하면 안쪽 반복 전에
D[i][k]가 무한대인 i를 건너뛰고,D[i],D[k]를 변수에 잡아 두면 빨라진다. 검증 코드의 풀이가 그렇게 짜여 있다.
6단계 · 실행 추적
예시 1: n = 6, s = 4, a = 6, b = 2. 플로이드–워셜을 끝낸 표에서 갈라지는 지점마다 더한다.
| 갈라지는 지점 k | D[4][k] | D[k][6] | D[k][2] | 합 |
|---|---|---|---|---|
| 1 | 10 | 25 | 63 | 98 |
| 2 | 66 | 48 | 0 | 114 |
| 3 | 51 | 26 | 22 | 99 |
| 4 (합승 안 함) | 0 | 35 | 66 | 101 |
| 5 | 34 | 2 | 46 | 82 |
| 6 | 35 | 0 | 48 | 83 |
5에서 갈라질 때 82원으로 가장 싸다. 합승하지 않으면 101원이다.
7단계 · 복잡도와 흔한 실수
플로이드–워셜 \(O(n^3)\), 갈라지는 지점 고르기 \(O(n)\)이다. n = 200, 모든 쌍에 요금이 있는 입력으로 재 보니 0.2초가 안 걸렸다.
- k = s(합승 안 함)를 빼먹는다. 범위를 1 ~ n 전체로 돌리면 저절로 들어간다.
- 요금을 한쪽 방향에만 적는다.
- 플로이드–워셜의 반복 순서를 바꿔 k를 안쪽에 둔다.
-
프로그래머스 스쿨, “합승 택시 요금” (https://school.programmers.co.kr/learn/courses/30/lessons/72413), 2026-09-30 조회. ↩