본 게시글은 권오흠 교수님의 영상과 여러 블로그들을 공부하고 정리한 글 입니다.

 

 

[ Back Tracking ]

 

 

'백 트랙킹' 이러니깐 사실 어떤 알고리즘인가 와 닿지가 않았는데 '되추적' 이라고 하니깐 확 와닿았다.

 

예상 되듯이 완전 탐색의 일종인데, 완전 탐색이 모든 경우의 수를 탐색하는 것이라면,

백 트랙킹은 탐색을 하는 도중 지금 경로가 답이 될 것 같지 않다면 그 경로를 더 이상 가지 않고 되돌아 가는 기법을 말한다.   반복문을 줄이기 때문에 더 효율적일것이라고 추론 할 수 있다.

( 사실 대표적인 완전 탐색인 DFS도 탐색을 하다가 if 문으로 조건 걸어주기만 한다면 다시 되돌아 올 수 있어서, 정확히 둘의 차이점은 잘 모르겠다.. )

 

DFS 와 백트랙킹의 정확한 차이점을 찾아보다 어떤 블로그 분의 좋은 글을 보게 됐는데 백트랙킹을 이해하는데 많은 도움이 됐다.

백트래킹(backtracking)이란?
솔루션을 찾는 과정에서, 유망(promising)하지 않은 후보해에 대해 대해 빠르게 포기하고 이전 단계로 되돌아(back track)가 다른 후보해를 찾는 알고리즘 기법이다.

DFS는 기본적으로 그래프 형태 자료구조에서 모든 정점을 탐색할 수 있는 알고리즘 중 하나이다. 깊이를 우선적으로 탐색하기에 재귀 또는 스택을 이용한다.

DFS 는 현재 지점에서 방문할 곳이 있으면 재귀 호출을 이용해서 계속 이동한다. 하지만 DFS 는 모든곳을 방문하기 때문에 굳이 목표지점이 있지 않는 경로로 빠져서 비효율적인 결과를 초래할수도 있다.

그래서 이와 같은 비효율적인 경로를 차단하고 목표지점에 갈수있는 가능성이 있는 루트를 검사하는 방법이 백트래킹 알고리즘이다. 백트래킹은 DFS에 가지치기 (Pruning) 를 통해 가도되지 않는 루트는 고려하지 않고 탐색하는 완전탐색 기법이다. 가지치기를 얼마나 잘하느냐에 따라서 효율이 극대화 될 수 있는 방법이다.
DFS는 기본적으로 모든 노드를 탐색하는 것이 목적이지만,
상황에 따라서 백트래킹 기법을 혼용하여 불 필요한 탐색을 그만두는 것이 가능하다. 

즉, DFS와 백트래킹은 유사한 부분이 있으며 기본적으로 사용 목적이 다르지만 두 기법을 혼용하여 사용하는 것이 가능하다.
완전히 다른 개념이 아니라 재귀 호출을 통한 기법 중 하나 이기 때문이다.

 

그럼 문제를 보고 이게 Back Tracking 이겠다 라고 어떻게 알 수 있을까?

보통 Back Tracking 문제 같다 싶으면 상태 공간 트리 를 생각하면 된다.

문제를 읽고 주어진 테스트 케이스를 시뮬레이션 해보면서 이해하다가 내가 상태 공간 트리를 사용하면서 경우의 수를 계산 하고 있다? 싶으면 백 트랙킹 의심해봐야 한다. 물론 백 트랙킹 문제의 많은 경우가 DP로도 풀린다고 한다.

그러나 아직 백트랙킹으로만 풀리는 문제들이 종종 있다고 한다.

 

 

백문이 불여일코  : 백번을 들어도 한번 코딩 해보는것만 못하다.

( 이 말 좋은것 같다. 블로그 이름도 이걸로 바꿔야겠다 :) )

 

자!  그럼 대표적인 백트랙킹 문제인 N-Queen 문제를 풀어보자.

 


 

https://www.acmicpc.net/problem/9663

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

https://programmers.co.kr/learn/courses/30/lessons/12952?language=cpp 

 

코딩테스트 연습 - N-Queen

가로, 세로 길이가 n인 정사각형으로된 체스판이 있습니다. 체스판 위의 n개의 퀸이 서로를 공격할 수 없도록 배치하고 싶습니다. 예를 들어서 n이 4인경우 다음과 같이 퀸을 배치하면 n개의 퀸은

programmers.co.kr


[ 최종 구현 ]

재귀로 구현하려면 아래와 같은 수도코드 형식을 띄는게 가장 간단하면서도 명확하다.

 


[ 코드 ]

#include<iostream>
#include<vector>

using std::cin; using std::cout;

int n, answer;
int cols[16];

bool promising(int level) {  // 대각선, 세로에 다른 퀸 없는지 검사.
	if (level == 1)return true;  // 첫번째 퀸은 어디든 가능.
	for (int i = level - 1; i >= 1; i--) { // 현재 레벨 전 퀸들 전부 검사.
		// 대각선 검사. ( 두 지점 가로 차이랑 = 세로 차이랑 같으면 대각선.
		if (std::abs(cols[level] - cols[i]) == (level - i)) {
			return false;
		} // 세로 검사.
		else if (cols[i] == cols[level]) {
			return false;
		}
	}
	return true;  // 전부 검사했는데도 false 안되면 true;
}

void nQueen(int level) {
	
	for (int i = 1; i <= n; i++) {
		cols[level] = i;

		if (promising(level)) { // cols[level]이 i가 될 수 있다면
			if (level == n) {
				answer++;
				return;
			}
			nQueen(level + 1);
		}
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> n;
	int level = 1;
	nQueen(level); // 1 부터 시작.
	cout << answer;
	return 0;
}
< 백 트랙킹 문제  >

https://www.acmicpc.net/step/34

 


 

[ Reference ]

 

 

 

https://thd0011.tistory.com/19

 

[알고리즘] 백트래킹 (Backtracking) 알고리즘

백트래킹 기본적으로 백트래킹은 '가능한 모든 방법을 탐색한다' 는데 기본 아이디어가 있다. 대표적인 완전 탐색 방법으로는 DFS (Depth First Search, 깊이 우선 탐색) 이 있다. DFS 는 현재 지점에서

thd0011.tistory.com

https://hongjw1938.tistory.com/88

 

알고리즘 - 백트래킹(Backtracking)

1. 백트래킹이란? 백트래킹은 알고리즘 기법 중 하나로, 재귀적으로 문제를 하나씩 풀어나가되 현재 재귀를 통해 확인 중인 상태(노드)가 제한 조건에 위배되는지(유망하지 않은지) 판단하고 그

hongjw1938.tistory.com

https://bunnnybin.tistory.com/entry/%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9-Backtracking-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%B4%EB%9E%80

 

백트래킹 (Backtracking) 알고리즘이란?

백트래킹이란? 해를 찾아가는 도중, 지금의 경로가 해가 될 것 같지 않으면 그 경로를 더이상 가지 않고 되돌아가는(Backtracking) 기법을 말한다. -> 반복문의 횟수를 줄여서 효율적이다!!! 좀더 정

bunnnybin.tistory.com

 

'CS > Algorithm' 카테고리의 다른 글

에라토스테네스의 체  (0) 2021.12.25
최단 경로 ② ( Floyd - Warshall )  (0) 2021.11.17
최단 경로 & 그래프 문제 유형  (0) 2021.11.17
Kruskal ( Union - Find )  (0) 2021.11.12
MST ( Minimum Spanning Tree ) - Kruskal , Prim  (0) 2021.11.11

+ Recent posts