코딩고치

[파이썬][알고리즘] 백트래킹 본문

파이썬/알고리즘

[파이썬][알고리즘] 백트래킹

코딩고치 2020. 5. 21. 12:12

백 트래킹 기법

  • 백 트래킹 또는 퇴각 검색이라 칭함
  • 제약 조건 만족 문제를 풀기 위한 전략
    • 후보군의 제약 조건을 체크하다가 만족할 수 없다고 판단되면 backtrack (다시는 이 후보군을 체크하지 않음), 그 후 다른 후보군으로 넘어감
    • 계산의 양을 줄일 수 있음
  • 모든 경우의 수를 상태 공간 트리로 표현
    • 각 후보군을 DFS로 탐색
    • 제약기 맞지 않으면 해의 후보가 될만한 곳으로 넘어가서 탐색
    • Promising: 조건이 맞는지 검사
    • Pruning: 조건이 맞지 않으면 다른 루트로 가서 탐색, 시간 절약
  • DFS로 탐색을 진행하면서 조건에 부합하는지 체크하고 부합하지 않으면 다른 루트로 가서 DFS 탐색을 진행

N Queen 문제

  • NxN 크기의 체스판에 N개의 퀸을 서로 공격할 수 없도록 배치하는 문제

Pruning

  • 한 행에는 하나의 퀸만 위치함
  • 체스판을 좌표로 나타낸 후 맨 위에 있는 행부터 퀸을 배치
  • 다음 행에 이전에 배치한 퀸이 이동할 수 없는 위치를 찾아 퀸 배치
  • 이전 행에 배치한 퀸으로 인해 다음 행에 퀸을 놓을 수 없는 경우 퀸을 배치하지 않고 이전 퀸의 자리 이동
  • 이를 이용하여 트리형태로 만듦

Promising

  • 퀸의 이동 경로에서 수직과 대각선을 체크
    • 한 행에 한개의 퀸만 위치하므로 수평 체크는 필요 없음
  • 수직 체크: 열이 달라야 함
  • 대각선 체크: 행과 열의 차이가 같은지 다른지 확인 (같으면 대각선에 위치한 것)

코드 작성

def nqueen(n):
    result = []
    dfs(n, 0, [], result)
    return result


def dfs(n, current_row, current_candidate, result):
    # 배치 종료
    if current_row == n:
        result.append(current_candidate[:])
        return

    # current_row에서 배치할 수 있는 col 찾기
    for candidate_col in range(n):
        if possible(current_candidate, candidate_col):
            current_candidate.append(candidate_col)
            dfs(n, current_row + 1, current_candidate, result)
            current_candidate.pop()


# 이전에 배치한 퀸과 같은 열에 있거나 대각선에 있으면 False
def possible(candidate, current_col):
    current_row = len(candidate)
    for queen_row in range(current_row):
        if candidate[queen_row] == current_col or abs(candidate[queen_row] - current_col) == current_row - queen_row:
            return False
    return True
nqueen(4)
[[1, 3, 0, 2], [2, 0, 3, 1]]
nqueen(5)
[[0, 2, 4, 1, 3],
 [0, 3, 1, 4, 2],
 [1, 3, 0, 2, 4],
 [1, 4, 2, 0, 3],
 [2, 0, 3, 1, 4],
 [2, 4, 1, 3, 0],
 [3, 0, 2, 4, 1],
 [3, 1, 4, 2, 0],
 [4, 1, 3, 0, 2],
 [4, 2, 0, 3, 1]]
Comments