♦️백트래킹(Backtracking)에 활용
모든 경우를 탐색하지만, 가능성이 없는 경로는 미리 포기한다. 쓸데없는 재귀 호출을 줄여서 속도를 높일 수 있다.
예시 문제 [N-Queen] : N×N 체스판에 N개의 퀸을 놓을 수 있는 경우의 수를 구하라. 단, 퀸은 같은 행, 열, 대각선에 놓일 수 없다.
1. 백트래킹
- 한 줄씩 퀸을 배치하면서 모든 가능한 경우를 탐색
- 만약 조건을 만족하지 않으면 즉시 탐색을 중단 (Pruning)
2. 프루닝
- 같은 열이나 같은 대각선에 퀸이 있으면 가지치기!
def is_safe(row, col, queens):
"""현재 (row, col)에 놓을 수 있는지 체크"""
for r, c in enumerate(queens): # 이전에 놓은 퀸들의 위치
if c == col or abs(r - row) == abs(c - col):
# 같은 열 or 같은 대각선에 퀸이 있으면 배치 불가능
return False
return True
def backtrack(n, row, queens):
"""백트래킹으로 모든 경우 탐색하며 퀸 배치"""
if row == n: # 모든 퀸을 배치 완료한 경우
return 1
count = 0
for col in range(n): # 현재 행의 모든 열에 퀸 놓아보기
if is_safe(row, col, queens): # Pruning: 배치 가능한 경우에만 진행
queens.append(col)
count += backtrack(n, row + 1, queens) # 다음 행으로 이동(재귀 호출)
queens.pop() # 되돌리기(백트래킹)
return count
def solve_n_queens(n):
return backtrack(n, 0, []) # 0번째 행부터 시작
print(solve_n_queens(8))
♦️DP에 활용
예시 문제: 피보나치 수열
📍Pruning 없이 계산했을 때
def fibonacci(n):
if n == 0 or n == 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2) # 중복 계산 발생
문제점: 같은 값을 여러 번 계산해서 시간 초과가 발생할 수 있음.
📍 Pruning + 메모이제이션 사용
memo = {}
def fibonacci(n):
if n == 0 or n == 1:
return n
if n in memo: # Pruning: 이미 계산된 값이면 다시 계산하지 않음
return memo[n]
memo[n] = fibonacci(n - 1) + fibonacci(n - 2)
return memo[n]
print(fibonacci(50)) # O(n)으로 해결 가능!
'코딩 테스트' 카테고리의 다른 글
브루트포스와 프루닝 (0) | 2025.02.11 |
---|---|
MST(Minimum Spanning Tree, 최소 신장 트리): 크루스칼 알고리즘 (1) | 2025.02.07 |
그래프와 최단 거리 문제: MST & TSP (0) | 2025.02.06 |
[python에서 priority queue 자료구조 사용하기 / heapq] (0) | 2025.02.03 |
스택과 큐 (0) | 2023.11.19 |