Skip to content

Commit ce8e99c

Browse files
committed
[Gold II] Title: 스타트 택시, Time: 28 ms, Memory: 79520 KB -BaekjoonHub
1 parent b5f9b3d commit ce8e99c

2 files changed

Lines changed: 192 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# [Gold II] 스타트 택시 - 19238
2+
3+
[문제 링크](https://www.acmicpc.net/problem/19238)
4+
5+
### 성능 요약
6+
7+
메모리: 79520 KB, 시간: 28 ms
8+
9+
### 분류
10+
11+
구현, 그래프 이론, 그래프 탐색, 시뮬레이션, 너비 우선 탐색
12+
13+
### 제출 일자
14+
15+
2026년 1월 4일 17:55:29
16+
17+
### 문제 설명
18+
19+
<p>스타트링크가 "스타트 택시"라는 이름의 택시 사업을 시작했다. 스타트 택시는 특이하게도 손님을 도착지로 데려다줄 때마다 연료가 충전되고, 연료가 바닥나면 그 날의 업무가 끝난다.</p>
20+
21+
<p>택시 기사 최백준은 오늘 M명의 승객을 태우는 것이 목표이다. 백준이 활동할 영역은 N×N 크기의 격자로 나타낼 수 있고, 각 칸은 비어 있거나 벽이 놓여 있다. 택시가 빈칸에 있을 때, 상하좌우로 인접한 빈칸 중 하나로 이동할 수 있다. 알고리즘 경력이 많은 백준은 특정 위치로 이동할 때 항상 최단경로로만 이동한다.</p>
22+
23+
<p>M명의 승객은 빈칸 중 하나에 서 있으며, 다른 빈칸 중 하나로 이동하려고 한다. 여러 승객이 같이 탑승하는 경우는 없다. 따라서 백준은 한 승객을 태워 목적지로 이동시키는 일을 M번 반복해야 한다. 각 승객은 스스로 움직이지 않으며, 출발지에서만 택시에 탈 수 있고, 목적지에서만 택시에서 내릴 수 있다.</p>
24+
25+
<p>백준이 태울 승객을 고를 때는 현재 위치에서 최단거리가 가장 짧은 승객을 고른다. 그런 승객이 여러 명이면 그중 행 번호가 가장 작은 승객을, 그런 승객도 여러 명이면 그중 열 번호가 가장 작은 승객을 고른다. 택시와 승객이 같은 위치에 서 있으면 그 승객까지의 최단거리는 0이다. 연료는 한 칸 이동할 때마다 1만큼 소모된다. 한 승객을 목적지로 성공적으로 이동시키면, 그 승객을 태워 이동하면서 소모한 연료 양의 두 배가 충전된다. 이동하는 도중에 연료가 바닥나면 이동에 실패하고, 그 날의 업무가 끝난다. 승객을 목적지로 이동시킨 동시에 연료가 바닥나는 경우는 실패한 것으로 간주하지 않는다.</p>
26+
27+
<p style="text-align: center;"><img alt="" src="https://upload.acmicpc.net/b4dfd78f-5276-44a4-a1f1-a5ccde6fbc8b/-/preview/" style="width: 395px; height: 396px;"></p>
28+
29+
<p style="text-align: center;"><그림 1></p>
30+
31+
<p><그림 1>은 택시가 활동할 영역의 지도를 나타내며, 택시와 세 명의 승객의 출발지와 목적지가 표시되어 있다. 택시의 현재 연료 양은 15이다. 현재 택시에서 각 손님까지의 최단거리는 각각 9, 6, 7이므로, 택시는 2번 승객의 출발지로 이동한다.</p>
32+
33+
<table class="table table table-bordered" style="width: 100%;">
34+
<tbody>
35+
<tr>
36+
<td style="width: 50%; text-align: center;">
37+
<p><img alt="" src="https://upload.acmicpc.net/3a0360d0-7aa4-4f6e-89aa-8f29ceb3db8d/-/preview/" style="width: 358px; height: 355px;"></p>
38+
39+
<p><그림 2></p>
40+
</td>
41+
<td style="width: 50%; text-align: center;">
42+
<p><img alt="" src="https://upload.acmicpc.net/fb1d41e5-a420-4957-8fe8-1a6f822b284e/-/preview/" style="width: 355px; height: 354px;"></p>
43+
44+
<p><그림 3></p>
45+
</td>
46+
</tr>
47+
</tbody>
48+
</table>
49+
50+
<p><그림 2>는 택시가 2번 승객의 출발지로 가는 경로를, <그림 3>은 2번 승객의 출발지에서 목적지로 가는 경로를 나타낸다. 목적지로 이동할 때까지 소비한 연료는 6이고, 이동하고 나서 12가 충전되므로 남은 연료의 양은 15이다. 이제 택시에서 각 손님까지의 최단거리는 둘 다 7이므로, 택시는 둘 중 행 번호가 더 작은 1번 승객의 출발지로 이동한다.</p>
51+
52+
<table class="table table table-bordered" style="width: 100%;">
53+
<tbody>
54+
<tr>
55+
<td style="width: 50%; text-align: center;">
56+
<p><img alt="" src="https://upload.acmicpc.net/a4ad059c-f909-4cf2-a401-9d72a69a2549/-/preview/" style="width: 355px; height: 356px;"></p>
57+
58+
<p><그림 4></p>
59+
</td>
60+
<td style="width: 50%; text-align: center;">
61+
<p><img alt="" src="https://upload.acmicpc.net/3abc49bb-33a3-4828-a6c3-1be22fd3967d/-/preview/" style="width: 357px; height: 356px;"></p>
62+
63+
<p><그림 5></p>
64+
</td>
65+
</tr>
66+
</tbody>
67+
</table>
68+
69+
<p><그림 4>와 <그림 5>는 택시가 1번 승객을 태워 목적지로 이동시키는 경로를 나타낸다. 남은 연료의 양은 15 - 7 - 7 + 7×2 = 15이다.</p>
70+
71+
<table class="table table table-bordered" style="width: 100%;">
72+
<tbody>
73+
<tr>
74+
<td style="width: 50%; text-align: center;">
75+
<p><img alt="" src="https://upload.acmicpc.net/86aa0566-f468-4343-a83d-d978f0120cec/-/preview/" style="width: 354px; height: 353px;"></p>
76+
77+
<p><그림 6></p>
78+
</td>
79+
<td style="width: 50%; text-align: center;">
80+
<p><img alt="" src="https://upload.acmicpc.net/aebc9d40-2c56-4e6c-b914-d8d9b55f8ff5/-/preview/" style="width: 362px; height: 354px;"></p>
81+
82+
<p><그림 7></p>
83+
</td>
84+
</tr>
85+
</tbody>
86+
</table>
87+
88+
<p><그림 6>과 <그림 7>은 택시가 3번 승객을 태워 목적지로 이동시키는 경로를 나타낸다. 최종적으로 남은 연료의 양은 15 - 5 - 4 + 4×2 = 14이다.</p>
89+
90+
<p>모든 승객을 성공적으로 데려다줄 수 있는지 알아내고, 데려다줄 수 있을 경우 최종적으로 남는 연료의 양을 출력하는 프로그램을 작성하시오.</p>
91+
92+
### 입력
93+
94+
<p>첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N<sup>2</sup>, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다.</p>
95+
96+
<p>다음 줄부터 N개의 줄에 걸쳐 백준이 활동할 영역의 지도가 주어진다. 0은 빈칸, 1은 벽을 나타낸다.</p>
97+
98+
<p>다음 줄에는 백준이 운전을 시작하는 칸의 행 번호와 열 번호가 주어진다. 행과 열 번호는 1 이상 N 이하의 자연수이고, 운전을 시작하는 칸은 빈칸이다.</p>
99+
100+
<p>그다음 줄부터 M개의 줄에 걸쳐 각 승객의 출발지의 행과 열 번호, 그리고 목적지의 행과 열 번호가 주어진다. 모든 출발지와 목적지는 빈칸이고, 모든 출발지는 서로 다르며, 각 손님의 출발지와 목적지는 다르다.</p>
101+
102+
### 출력
103+
104+
<p>모든 손님을 이동시키고 연료를 충전했을 때 남은 연료의 양을 출력한다. 단, 이동 도중에 연료가 바닥나서 다음 출발지나 목적지로 이동할 수 없으면 -1을 출력한다. 모든 손님을 이동시킬 수 없는 경우에도 -1을 출력한다.</p>
105+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import Foundation
2+
3+
let input = readLine()!.split(separator: " ").map { Int($0)! }
4+
let N = input[0]
5+
let M = input[1]
6+
var fuel = input[2]
7+
8+
let dr = [-1, 0, 0, 1]
9+
let dc = [0, -1, 1, 0]
10+
11+
var map = [[Int]]()
12+
for _ in 0..<N {
13+
map.append(readLine()!.split(separator: " ").map { Int($0)! })
14+
}
15+
16+
var taxiPos = readLine()!.split(separator: " ").map { Int($0)! - 1 }
17+
18+
var passengers = [Int: (Int, Int)]()
19+
for _ in 0..<M {
20+
let p = readLine()!.split(separator: " ").map { Int($0)! - 1 }
21+
let key = p[0] * N + p[1]
22+
passengers[key] = (p[2], p[3])
23+
}
24+
25+
func bfs(_ sr: Int, _ sc: Int) -> [[Int]] {
26+
var dist = Array(repeating: Array(repeating: -1, count: N), count: N)
27+
var q = [(sr, sc)]
28+
var idx = 0
29+
dist[sr][sc] = 0
30+
31+
while idx < q.count {
32+
let (r, c) = q[idx]
33+
idx += 1
34+
35+
for d in 0..<4 {
36+
let nr = r + dr[d]
37+
let nc = c + dc[d]
38+
if nr < 0 || nr >= N || nc < 0 || nc >= N { continue }
39+
if map[nr][nc] == 1 || dist[nr][nc] != -1 { continue }
40+
dist[nr][nc] = dist[r][c] + 1
41+
q.append((nr, nc))
42+
}
43+
}
44+
return dist
45+
}
46+
47+
for _ in 0..<M {
48+
let distMap = bfs(taxiPos[0], taxiPos[1])
49+
50+
var candidate: (Int, Int, Int)? = nil // (거리, r, c)
51+
52+
for (key, _) in passengers {
53+
let r = key / N
54+
let c = key % N
55+
let d = distMap[r][c]
56+
if d == -1 { continue }
57+
58+
if candidate == nil ||
59+
d < candidate!.0 ||
60+
(d == candidate!.0 && (r < candidate!.1 || (r == candidate!.1 && c < candidate!.2))) {
61+
candidate = (d, r, c)
62+
}
63+
}
64+
65+
if candidate == nil || fuel < candidate!.0 {
66+
print(-1)
67+
exit(0)
68+
}
69+
70+
fuel -= candidate!.0
71+
taxiPos = [candidate!.1, candidate!.2]
72+
73+
let dest = passengers.removeValue(forKey: candidate!.1 * N + candidate!.2)!
74+
let distToDest = bfs(taxiPos[0], taxiPos[1])
75+
let d = distToDest[dest.0][dest.1]
76+
77+
if d == -1 || fuel < d {
78+
print(-1)
79+
exit(0)
80+
}
81+
82+
fuel -= d
83+
fuel += d * 2
84+
taxiPos = [dest.0, dest.1]
85+
}
86+
87+
print(fuel)

0 commit comments

Comments
 (0)