Skip to content

Commit

Permalink
feat : [Algorithm] 백트래킹 정리 (#11)
Browse files Browse the repository at this point in the history
* feat : [Algorithm] 백트래킹 정리

* fix : 이미지 깨진거 수정
  • Loading branch information
cywin1018 authored Jan 1, 2025
1 parent 606be0c commit 29fb7f2
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions Algorithm/백트래킹.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
## 백트래킹 알고리즘이란?

> 해를 찾는 도중 해가 아니어서 막히면, 되돌아가서 해를 찾아가는 기법.
> 최적화 혹은 결정 문제를 푸는 방법
- 만약 N!의 경우의 수를 가진 문제에서 최악의 경우에는 여전히 지수함수 시간이 필요해서 처리가 불가능할 수도 있음
- 즉, 모든 경우의 수 중에서 특정한 조건을 만족하는 경우만 살펴보는 것이다.
- 주로 재귀함수로 구현됨

### 예시문제 : BOJ 15649 - N과 M(1)

![image](https://github.com/user-attachments/assets/ddca3413-338b-445c-b527-6c4d07f5442f)

- 위의 문제를 보면, 무식하게 M중 중첩 반복문으로 탐색을 하고, 각 순열마다 중복 체크를 해서 해결할 수는 있다.
- 그러나, 시간제한을 보면 1초라고 명시되어 있는데, 위의 방법으로 시간복잡도를 계산해보자.
- M중 중첩 반복문을 각 자리에서 N개의 숫자를 모두 시도한다고 했을 때, O(N^M)이다.
- 각 순열마다 중복체크를 한다면 O(M)이다
- 즉, 도합 O(N^M\*M )의 시간복잡도가 걸리며, 최악의 경우 (N=8,M=8)에는 총1억3천번 정도의 연산을 하게된다
- 대충 1초 = 1억이라고 치고 계산하면 1.3초 정도 걸리는데, 이러면 시간제한을 맞출 수 없게된다

### 해결법

``` c++
void recur (int cnt) {
if(cnt==m) {
for(int i=0;i<m;i++) {
cout << A[i] << " ";
}
cout << '\n';
}
for(int i=1;i<=n;i++) {
if(vis[i])continue;
vis[i]=true;
A[cnt]=i;
recur(cnt+1);
vis[i]=false;
}
}
```

- 위와 같이 재귀호출을 이용해서 구하면 시간 복잡도가 훨씬 줄어들게 된다.
- if(vis[i])continue를 통하여 가지치기(pruning)을 거치면서 연산이 줄어들게 되는것이다.
- 요약하자면 N!/(N-M)! 정도 걸리는데, N=8,M=8인 경우 대략 4만번의 연산을 하게 되므로, 기존의 1억3천번보다 훨씬 줄어든다는 것을 알 수 있다.

## 추천 문제

### N과 M 시리즈(1~9)

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

### 연산자 끼워넣기

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

0 comments on commit 29fb7f2

Please sign in to comment.