[백준] N-Queens 문제(Python) - 백트래킹

2022. 4. 27. 12:11·Algorithms 💻/BAEKJOON
반응형

# 문제 

즉, 상하좌우 대각선으로 이동하는 N개의 퀸을 서로 부딪히지 않도록 배열하는 방법 수를 리턴하는 문제이다. 백트래킹의 전형적인 문제 유형이라고 한다. 아래의 예시처럼 말을 놓는 경우의 수는 하나의 경우의 수가 될 것이다. 

 

# 입출력

 

# Idea

우선 해당 문제는 백트래킹 문제로, DFS 방법으로 문제를 푸는 방법을 고안할 수 있다. (백트래킹에 대해 궁금하신 분들은 여기를 참고!) 특히 이 문제를 처음 봤을 때, 나는 다음과 같이 DFS노드를 뻗으면 어떨지 생각을 했다. 각 raw별 좌표를 노드로 놓고, Depth는 raw 단위가 되도록 노드를 뻗는 것이다. 

특히 백트래킹은 유망한 노드(정답이 될 가능성이 있는 노드)이면 계속 DFS 탐색을 하고, 그렇지 않으면 탐색을 멈추고 위 depth의 노드로 돌아가는, 즉 효율을 추구하는 알고리즘 방법이다. 따라서 이 N-Queens 문제에서 "유망함" (즉 정답이 될 수 있는) 의 기준이란, 아마 Raw 단위로 탐색할 때 기존의 Queen의 위치와 상하좌우 대각선으로 만나지 않는 것일것이다. (그래야 정답이 될 수 있기 때문이다!) 

따라서 이 문제의 중요한 포인트는 "상하좌우 대각선에 해당 노드가 위치해있는지 체크하는 과정"이 존재해야 한다. 개인적으로 코드를 구현할 때 이 부분이 막막하게 느껴졌는데, 상하좌우 대각선을 체크하는 부분을 다음과 같이 구현할 수 있다. 

# 상하좌우 대각선 체크 함수
def check(n):
  for i in range(n):
    if (board[n] == board[i]) or (n-i == abs(board[n] - board[i])):    # 좌우에 있거나, 대각선에 있다면 
      return False 

  return True

위 코드에서 n은 특정 raw(=특정 depth)이다. 그리고 board에는 1차원 리스트로 해당 raw에서의 현재 queen의 위치가 적재된다. 
즉, 이 코드에서 board[n]이란 n번째 raw에서 현재 queen의 위치가 되는 것이다. 따라서 반복문을 통해 특정 raw의 좌표를 훑으면서, 현재 raw에서의 queen의 위치와 상하좌우 대각선에서 만나는지 검사하는 함수이다. 여기서 좌우와 대각선을 검사하는 방법은 다음 조건과 같다. (참고로 특정 raw의 노드들만 보는것이므로, 상하는 고려할 필요가 없다) 

  • 좌우 검사 : 단순히 현재 queen의 column 위치와 기존에 적재된 queen 중 특정 queen의 column 위치가 같은지 확인하면 된다. 
    (board[n] == board[i] 부분) 
  • 대각선 검사 : (현재 queen의 raw - 기존의 queen의 raw)가 |현재 queen의 column - 기존 queen의 column| 과 같은지 확인하면 된다. (n-i == abs(board[n] - board[i] 부분) 

 

 

# Code

위 아이디어를 코드로 구현하면 다음과 같다. board 1차원 리스트에는 raw별 queen이 적재되는 시스템이다. 즉, 아래와 같은 사진으로 이해하면 되겠다. 

"""
N queens 문제 
  - 내 최대 고민은 대각선, 가로세로 위치를 어떻게 확인할 것인가? (퀸 위치와 어떻게 비교할 것인가)
  - 대각선 조건 : (놓으려는 자리의 행 - 모든 행 중 하나) == abs(놓으려는 자리의 열 - 모든 행 중 하나의 열)
"""

def nqueen(depth):     
  global result
  
  # depth가 N일 때 > 모든 퀸을 다 놓은 것
  if depth == N : 
    result += 1 
    return 

  # depth별 반복문 
  for i in range(N):

    # 해당 depth를 visited 하지 않았을 때 
    if visited[i] == False : 
      board[depth] = i     # (depth, i)에 퀸 올리기 (여기서 depth는 raw, i는 column에 해당
      
      if check(depth):
        visited[i] = True
        nqueen(depth + 1)     # 그 다음 열로 넘어감 
        visited[i] = False    # 다시 false로 설정해 백트래킹 


# 모든 열에대해 퀸과 대각선, 좌우에 위치해 있는지 체크 
def check(n):
  for i in range(n):

    # 좌우에 있거나, 대각선에 있다면 
    # TODO(여기서 기존 queen이 어떻게 적재되고 있는걸까?)
    if (board[n] == board[i]) or (n-i == abs(board[n] - board[i])):
      return False

  return True

# main 
if __name__ == '__main__':
  N = int(input())    # dfs의 depth에 해당함 
  # depth별 적재 
  board = [0] * N     # 1차원 리스트로 적재 
  visited = [False] * N
  result = 0 

  nqueen(0)
  print(result)

 

참고로 위 코드 중에서 이 부분에서 백트래킹이 일어난다. visited를 다시 False로 설정하는 과정이다. 

  if check(depth):
    visited[i] = True
    nqueen(depth + 1)     # 그 다음 열로 넘어감 
    visited[i] = False    # 다시 false로 설정해 백트래킹

 

반응형
저작자표시 (새창열림)

'Algorithms 💻 > BAEKJOON' 카테고리의 다른 글

[백준] 치킨배달(Python) - 구현 & 백트래킹  (0) 2022.05.23
[백준] 스타트와 링크(Python) - 백트래킹  (0) 2022.05.05
[백준] 1,2,3 더하기(Python) - 백트래킹 & 1차원 dfs 탐색  (0) 2022.04.20
[백준] 로또(Python) - 백트래킹 & 1차원 dfs 탐색  (0) 2022.04.07
[백준] 에디터(Python) - Stack  (0) 2022.03.26
'Algorithms 💻/BAEKJOON' 카테고리의 다른 글
  • [백준] 치킨배달(Python) - 구현 & 백트래킹
  • [백준] 스타트와 링크(Python) - 백트래킹
  • [백준] 1,2,3 더하기(Python) - 백트래킹 & 1차원 dfs 탐색
  • [백준] 로또(Python) - 백트래킹 & 1차원 dfs 탐색
당니이
당니이
씩씩하게 공부하기 📚💻
  • 당니이
    다은이의 컴퓨터 공부
    당니이
  • 전체
    오늘
    어제
    • 분류 전체보기 (136)
      • Achieved 👩🏻 (14)
        • 생각들 (2)
        • TIL (6)
        • Trial and Error (1)
        • Inspiration ✨ (0)
        • 미국 박사 준비 🎓 (1)
      • Computer Vision💖 (39)
        • Basic (9)
        • Video (5)
        • Continual Learning (7)
        • Generative model (2)
        • Domain (DA & DG) (5)
        • Multimodal (8)
        • Multitask Learning (1)
        • Segmentation (1)
        • Colorization (1)
      • RL 🤖 (1)
      • Autonomous Driving 🚙 (11)
        • Geometry (4)
        • LiDAR 3D Detection (1)
        • Trajectory prediction (2)
        • Lane Detection (1)
        • HDmap (3)
      • Linux (15)
      • PyTorch👩🏻‍💻 (10)
      • Linear Algebra (2)
      • Python (5)
      • NLP (10)
        • Article 📑 (1)
      • Algorithms 💻 (22)
        • Basic (8)
        • BAEKJOON (8)
        • Programmers (2)
      • ML (1)
        • 통계적 머신러닝(20-2) (1)
      • SQL (3)
      • 기초금융 💵 (1)
  • 블로그 메뉴

    • 홈
    • About me
  • 링크

    • 나의 소박한 github
    • Naver 블로그
  • 공지사항

  • 인기 글

  • 태그

    LLM
    코딩테스트
    리눅스
    pytorch
    백준
    Python
    Incremental Learning
    domain adaptation
    백트래킹
    dfs
    Linux
    conda
    til
    알고리즘
    CL
    자료구조
    continual learning
    domain generalization
    CV
    NLP
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
당니이
[백준] N-Queens 문제(Python) - 백트래킹
상단으로

티스토리툴바