깊이 우선 탐색(DFS) (2) - 여행경로
깊이 우선 탐색(DFS) (2) - 여행경로
여행 경로
주어진 항공권을 모두 사용하여 ICN에서 출발하는 여행 경로를 찾는 문제
알파벳 순서가 앞서는 경로를 우선적으로 선택하고, 모든 항공권이 사용되어야 하며 모든 도시를 방문할 수 없는 경우는 없다.
풀이 전략
그래프 생성
항공권 정보를 바탕으로 인접 리스트 형태의 그래프를 생성한다. 각 공항에서 갈 수 있는 공항들을 알파벳 순으로 정렬한다.
- DFS(깊이 우선 탐색)
- 재귀적으로 경로를 탐색하며 모든 항공권을 사용했는지 확인한다.
- 탐색 과정에서 경로를 기록하고, 가능한 경로를 사전순으로 반환한다.
경로 완성
모든 티켓이 사용된 경로를 반환하며, 여러 경로가 가능할 경우 알파벳 순서를 따른다.
알고리즘 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
unction solution(game_board, table) {
const n = game_board.length;
// 방향 벡터: 상, 하, 좌, 우
const directions = [
[-1, 0], [1, 0], [0, -1], [0, 1]
];
// 블록 추출 함수 (DFS 기반)
const extractBlock = (board, x, y, value) => {
const block = [];
const queue = [[x, y]];
board[x][y] = -1; // 방문 표시
block.push([x, y]);
while (queue.length) {
const [cx, cy] = queue.shift();
for (const [dx, dy] of directions) {
const nx = cx + dx;
const ny = cy + dy;
if (
nx >= 0 && ny >= 0 && nx < n && ny < n &&
board[nx][ny] === value
) {
board[nx][ny] = -1; // 방문 표시
queue.push([nx, ny]);
block.push([nx, ny]);
}
}
}
// 블록 정렬 및 기준점(0, 0)으로 이동
block.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
const [baseX, baseY] = block[0];
return block.map(([bx, by]) => [bx - baseX, by - baseY]);
};
// 블록 회전 함수
const rotateBlock = (block) => {
return block.map(([x, y]) => [y, -x])
.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
};
// 블록 비교 함수
const isSameBlock = (block1, block2) => {
if (block1.length !== block2.length) return false;
for (let i = 0; i < block1.length; i++) {
if (block1[i][0] !== block2[i][0] || block1[i][1] !== block2[i][1]) {
return false;
}
}
return true;
};
// 보드에서 모든 블록 추출
const findBlocks = (board, value) => {
const blocks = [];
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (board[i][j] === value) {
blocks.push(extractBlock(board, i, j, value));
}
}
}
return blocks;
};
// 게임 보드의 빈칸 (0)을 블록으로 추출
const emptySpaces = findBlocks(game_board, 0);
// 테이블의 퍼즐 조각 (1)을 블록으로 추출
const puzzleBlocks = findBlocks(table, 1);
let filledSpaces = 0;
// 빈칸과 퍼즐 조각 매칭
for (const empty of emptySpaces) {
for (let i = 0; i < puzzleBlocks.length; i++) {
const puzzle = puzzleBlocks[i];
let matched = false;
for (let rotation = 0; rotation < 4; rotation++) {
if (isSameBlock(empty, puzzle)) {
filledSpaces += puzzle.length;
puzzleBlocks.splice(i, 1); // 사용한 퍼즐 조각 제거
matched = true;
break;
}
puzzle = rotateBlock(puzzle); // 회전
}
if (matched) break;
}
}
return filledSpaces;
}
시간 복잡도
그래프 생성
주어진 항공권을 정렬하는 데 O(ElogE)의 시간이 소요된다. 여기서 E는 항공권의 수이다.
DFS 탐색
각 항공권을 정확히 한 번씩 탐색하므로 O(E)의 시간이 소요된다.
결과적으로 시간 복잡도는 O(ElogE)이다.
This post is licensed under CC BY 4.0 by the author.