[Baekjoon] 9663. N-Queen

1 minute read

N-Queen

문제 설명


문제

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.

N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N < 15)

출력

첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.

예제 입력 1 복사

8

예제 출력 1 복사

92


문제 풀이


N-Queen은 유명한 백트래킹 문제이다.


1번 풀이(14396ms, PyPy3)

col_loc이라는 queen들의 열의 위치를 저장하는 리스트를 만들고, 해당 위치에 놓을 수 있는 지 검사하기 위해 col_loc의 값들을 이용해 계산을 합니다.

col_loc = [] # 0~7번째 행에 위치한 열의 위치
def find_nqueen(N, row, cnt):
    global col_loc
    if row == N:
        return cnt+1

    for col in range(N):
        for line in range(len(col_loc)):
            # 1. 같은 열인지, 2. 같은 우상향 대각선인지, 3. 같은 우하향 대각선인지
            if col == col_loc[line] or row + col == line + col_loc[line]\
                                    or row - col == line - col_loc[line]:
                break
        else:
            col_loc.append(col)
            cnt = find_nqueen(N,row+1,cnt)
            col_loc.pop()

    return cnt

print(find_nqueen(int(input()),0,0))


2번 풀이(6860ms, PyPy3)

열의 위치를 저장하는 것이 아니라, queen이 배치될 때마다 해당 위치의 열, 우상향 대각선, 우하향 대각선을 True로 설정하여 다른 queen이 배치되지 못하도록 합니다.

해당 풀이의 경우 정석적인 풀이라고 볼 수는 없지만, 계산 과정이 없고 인덱스 참조만 하기 때문에 시간이 훨씬 줄어듭니다.

n = int(input())
count = 0
column,rightup,rightdown = [False]*n,[False]*(2*n-1),[False]*(2*n-1)

def NQueen(line):
  global count
  if line == n:
    count += 1
    return
  else:
    for index in range(n):
      if not (column[index] or rightup[line+index] or rightdown[line-index+n-1]):
        column[index] = rightup[line+index] = rightdown[line-index+n-1] = True
        NQueen(line+1)
        column[index] = rightup[line+index] = rightdown[line-index+n-1] = False

NQueen(0)
print(count)


파이썬은 가독성이 좋은 interpreter 언어이기 때문에 compiler 언어들보다 속도면에서 확연하게 느립니다.

따라서 이러한 재귀 알고리즘에 있어 파이썬 언어는 좋은 선택은 아닙니다. 실제로 PyPy3가 아닌 Python3로 제출 시 시간 초과가 발생합니다.

Leave a comment