https://www.acmicpc.net/problem/9663
앞선 문제인 N과 M에서 사용되는 DFS를 활용한 문제이다.
중요한 아이디어는 같은 row에는 퀸이 하나밖에 존재할 수 없으며, 또 하나는 무조건 있다는 것이다.
이번 row에는 퀸이 어디에 와야할 지 column을 차례대로 늘려가면서 findColumn 함수를 통해 검사한다.
개인적으로는 row와 col이 서로 헷갈리고, for문의 range를 정하는 것 때문에 어려웠던 문제이다.
코드 설명은 주석으로 대신한다. 밑에서부터 보면 된다.
def isPossible(row, col): # 위 혹은 양방향 대각선에 퀸이 있는지 검사
# 좌우는 볼 필요가 없다. 하나의 row에는 하나의 퀸!
# 위 (아래를 안 보는 이유는 아직 다음 row 자체를 안 봤기 때문
for i in range(1, n): # 주의: 1부터다. 0으로하면 7번째 줄에서 자기 자신과 같은지 검사하게 됨
if row-i >= 0: # row를 1씩 줄여가되 음수가 되지 않도록 한다.
if chess[row-i][col]: # 퀸을 발견했다
return False
# \ 방향 대각선. row, col에서 1씩 빼면서 확인
for i in range(1, n):
if row-i >= 0 and col-i >= 0:
if chess[row-i][col-i]:
return False
# / 방향 대각선. row는 -1, col은 +1 (그림으로 생각해보자)
for i in range(1, n):
if row-i >= 0 and col+i < n:
if chess[row-i][col+i]:
return False
return True # 위 모든 검사를 통과했다면 그거슨 퀸
def findColumn(row):
global answer # 전역변수를 함수 내에서 수정하기 위해 global 선언
if row == n: # 하나의 row에는 하나의 퀸이 무조건 들어가므로, row가 n이라면 퀸의 자리를 다 찾은 것임
answer += 1
return
for col in range(n): # row는 정해져 있으니 column을 1씩 증가시키면서 확인한다
if isPossible(row, col): # 놓을 수 있다면
chess[row][col] = True # True로 퀸의 자리를 표시
findColumn(row+1) # 다음 row에서 퀸의 자리를 찾는다
chess[row][col] = False # 재귀가 끝난 후, 백트래킹해야하므로 다시 False로 돌려놓는다
n = int(input())
chess = [[False]*n for _ in range(n)] # 체스판. True면 퀸이 있는 자리
answer = 0
findColumn(0) # 인자는 row. 0번째 row부터 퀸이 들어갈 column을 찾는다.
print(answer)
'알고리즘 > 백트래킹' 카테고리의 다른 글
2차원 배열에서 조합 선택하기 (0) | 2019.12.20 |
---|---|
14888. 연산자 끼워넣기 (0) | 2019.11.28 |
2580. 스도쿠 (0) | 2019.11.27 |
15650. N과 M (2) (0) | 2019.11.22 |
15649. N과 M(1) (0) | 2019.11.22 |