이번 포스팅에서는 백트래킹 방법(Backtracking)에 대해서 알아보겠습니다.

1.백트래킹이란?

정의

: 해를 찾는 도중에 ‘막히면’(해가 아니면) 되돌아가서 다시 해를 찾아가는 기법 즉 모든 경우의 수를 전부 고려하는 알고리즘이다.
일종의 트리 탐색 알고리즘이라고 봐도 된다.
방식에 따라서 깊이우선탐색(DFS)과 너비우선탐색(BFS)로 나뉜다.

1.1 DFS(Depth First Search) - 깊이우선탐색

: DFS는 상태공간을 나타낸 트리에서 바닥에 도달할 때까지 한 쪽 방향으로만 내려가는 방식이다. 미로찾기를 생각하면 쉽다. 한 방향으로 들어갔다가 막다른 길에 다다르면(=트리의 바닥에 도착) 왔던 길을 돌아가서 다른 방향으로 간다. 이러한 방법을 목표지점(=원하는 해)이 나올 때까지 반복한다. 재귀함수로 구현할 수 있으며, 재귀함수에 익숙하지 않다면 스택을 써서 할 수도 있다.

1.2 BFS(Breadth First Search) - 너비우선 탐색

: BFS는 모든 분기점을 다 검사하면서 진행하는 방식이다.
철수와 영희가 계단에서 가위바위보를 하며 게임을 하고 있을 때, 철수가 원하는 지점에 갈 수 있는 최소 승리 횟수는 얼마인가? 같은 문제에서 효과를 발휘한다. 이 경우 DFS는 깊이가 무한인 경우에 빠져나오지 못하며, 중복 방지를 한다고 치더라도 올바른 해를 찾는데 시간이 많이 걸린다. BFS는 모든 분기를 다 검색하면서 상태공간을 탐색한다. 철수가 이겼을 때, 비겼을 때, 졌을 때를 검사하고, 그 경우마다 각각 또다른 3가지 가능성을 전부 검사한다. 이러다가 어느 한 부분에서 원하는 해를 발견하면, 이것이 최단 거리가 된다.

BFS는 큐를 써서 구현한다. 각 경우를 검사하면서 발생하는 새로운 경우를 큐에 집어넣고, 검사한 원소는 큐에서 뺀다. BFS의 장점은 DFS가 못 건드리는 문제를 풀 수 있는 것이지만, 공간 복잡도가 지수 스케일로 폭발하기 때문에 가지치기를 제대로 안하면 DFS보다 빨리 오버플로우에 다다를 수 있다

1.3 예시

  • 미로 찾기, n-Queen, Map coloring, 부분 집합의 합
  • 입구에서 출구까지 가는 경로가 존재하는지 묻는 문제
  • 원소의 합이 조건에 맞는 부분 집합이 존재하는지 묻는 문제
  • 미로 찾기에서 출구까지 가는 경로 중에 최단 경로를 찾는 문제
  • 가지치기로 불필요한 경로 조기에 차단