티스토리 뷰

대각 공식을 몰라 애먹은 문제.. 남겨두고 다시 풀어보면 좋을 것 같아서 포스팅합니다!

 

https://www.acmicpc.net/problem/9663 

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

백트래킹으로 풀어야 한다는걸 알면서도 대각체크를 어떻게 해줘야할지 몰라 해설을 보고 풀었습니다.

스스로 푼게 아니기에 또 까먹을까봐 블로그 포스팅을 남기고 추후에 제가 보고 쉽게 이해하기 바라며 포스팅합니다!

우선 이 문제를 보고 처음 풀이 접근 방법을 떠올려보자면 많은 사람들이 이렇게 추측하겠죠!

퀸은 가로로 또는 세로로 공격이 가능하니까 행 하나당 하나의 퀸을 놓을 수 있겠다! 또는 열 하나에 하나의 퀸이 있겠다!

맞습니다! 첫 접근은 그렇게 하는게 맞구요! 문제는 대각은 어떻게 체크할까? 이겠죠!

이거는 수학적으로 쉬운 접근 방법이 있어요!

바로 배열에서 좌측대각과 우측 대각의 비밀이죠!

위 그림과 같은 3 x 3 배열이 있다고 칩시다. 좌측 대각선은 어떤 규칙이 보이시나요??

넹 좌측 대각의 x + y는 모두 같아요! 

우측 대각은 y-x와 같습니다.

하지만 코드상에서는 편의를 위해 0부터 시작하기 위해서 +n-1을 취해줬습니다!

위 성질들을 이용해서 백트래킹을 돌면서 

1. 같은 열에 있는지 체크 ( n개의 배열 )

2. 좌측 대각에 놓을 수 있는지 체크 (참고로! 대각은 2*n -1개의 배열의 개수를 가집니다!)

3. 우측 대각에 놓을 수 있는지 체크 (참고로! 대각은 2*n -1개의 배열의 개수를 가집니다!)

하면서 퀸을 놓으면 됩니다!

 

let n = Int(readLine()!)!

var check1 = Array(repeating: false, count: n)
var check2 = Array(repeating: false, count: 2*n-1)
var check3 = Array(repeating: false, count: 2*n-1)

var count = 0

func backTracking(_ curY: Int) {
    if curY == n { // 현재 뽑은 개수가 n과 같으면 종료
        count += 1
        return
    }
    
    for i in 0..<n {
        if check1[i] || check2[i+curY] || check3[curY-i+n-1] { continue }
        // 열|좌측대각|우측대각 방문 표시
        check1[i] = true
        check2[i+curY] = true
        check3[curY-i+n-1] = true
        
        backTracking(curY+1) // 이번 열에서 뽑고 다음 행 뽑으러
        
        // 열|좌측대각|우측대각 방문 표시 지우기 이번 행에선 이번 열을 안뽑는 경우로 분기
        check1[i] = false
        check2[i+curY] = false
        check3[curY-i+n-1] = false
    }
}
backTracking(0)

print(count)

'Algorithm > 백트래킹' 카테고리의 다른 글

[Swift] 백준[15649번] N과 M(1) 문제풀이  (0) 2023.04.03
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
공지사항
링크
Total
Today
Yesterday