Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 N-퀸 퍼즐의 유효한 해답인지 확인하는 프로그램

n × n 크기의 행렬이 하나의 체스판을 나타낸다고 가정해 봅시다. 행렬에는 1과 0만 존재하며, 1은 퀸(Queen)이 있는 칸, 0은 빈 칸을 의미합니다. 우리가 확인해야 할 것은 이 체스판이 N-퀸(N-Queen) 퍼즐의 유효한 해답인지 여부입니다.

N-퀸 문제에서 유효한 해답이 되려면 어떤 두 퀸도 서로를 공격할 수 없는 위치에 있어야 합니다. 즉, 같은 행, 같은 열, 같은 대각선 위에 두 개 이상의 퀸이 존재해서는 안 됩니다.

예를 들어 다음과 같은 입력이 주어졌을 때,

파이썬으로 N-퀸 퍼즐의 유효한 해답인지 확인하는 프로그램

출력 결과는 True가 됩니다.

문제 해결 접근 방식

이 문제는 네 개의 집합(set)을 활용하면 간단하게 해결할 수 있습니다. 핵심 아이디어는 다음과 같습니다.

  • 같은 행에 있는 퀸들은 행 번호(i)가 동일합니다.
  • 같은 열에 있는 퀸들은 열 번호(j)가 동일합니다.
  • 같은 ↘ 방향 대각선에 있는 퀸들은 (i − j) 값이 동일합니다.
  • 같은 ↗ 방향 대각선에 있는 퀸들은 (i + j) 값이 동일합니다.

따라서 다음 단계로 진행합니다.

  1. n := 행렬의 행 개수로 설정합니다.
  2. rows, cols, diags, rev_diags라는 네 개의 빈 집합을 생성합니다.
  3. 행렬의 모든 칸을 순회하면서 값이 1인 칸(퀸)을 발견하면:
    • i를 rows 집합에 추가
    • j를 cols 집합에 추가
    • (i − j)를 diags 집합에 추가
    • (i + j)를 rev_diags 집합에 추가
  4. 네 집합의 크기가 모두 n과 같으면 True를 반환하고, 그렇지 않으면 False를 반환합니다.

집합은 중복 값을 자동으로 제거하기 때문에, 두 퀸이 같은 행·열·대각선에 있다면 해당 집합의 크기가 줄어들게 됩니다. 따라서 최종적으로 모든 집합의 크기가 n이라면 어떤 퀸도 서로 공격하지 않는다는 의미입니다.

구현 예제

class Solution:
   def solve(self, matrix):
      n = len(matrix)

      rows = set()
      cols = set()
      diags = set()
      rev_diags = set()

      for i in range(n):
         for j in range(n):
            if matrix[i][j]:
               rows.add(i)
               cols.add(j)
               diags.add(i - j)
               rev_diags.add(i + j)

      return len(rows) == len(cols) == len(diags) == len(rev_diags) == n

ob = Solution()
matrix = [
   [0, 0, 0, 1, 0],
   [0, 1, 0, 0, 0],
   [0, 0, 0, 0, 1],
   [0, 0, 1, 0, 0],
   [1, 0, 0, 0, 0]
]
print(ob.solve(matrix))

입력

matrix = [
   [0, 0, 0, 1, 0],
   [0, 1, 0, 0, 0],
   [0, 0, 0, 0, 1],
   [0, 0, 1, 0, 0],
   [1, 0, 0, 0, 0]
]

출력

True

복잡도 분석

이 알고리즘은 행렬의 모든 칸을 한 번씩 순회하므로 시간 복잡도는 O(n²)이며, 네 개의 집합을 저장하기 위한 공간 복잡도 역시 O(n)입니다. 백트래킹 없이도 기존 배치의 유효성을 빠르게 검증할 수 있는 효율적인 방법입니다.