[백준] 9663번 N-Queen - 파이썬(Python)

2021. 9. 30. 19:35· 알고리즘/문제풀이
목차
  1. 문제 (링크)
  2. 나의 풀이
  3. 코드 설명 및 풀이법
  4. (추가 +)
728x90

문제 (링크)

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

 

9663번: N-Queen

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

www.acmicpc.net

 

나의 풀이

n = int(input())

ans = 0
row = [0] * n

def is_promising(x):
    for i in range(x):
        if row[x] == row[i] or abs(row[x] - row[i]) == abs(x - i):
            return False
    
    return True

def n_queens(x):
    global ans
    if x == n:
        ans += 1
        return

    else:
        for i in range(n):
            # [x, i]에 퀸을 놓겠다.
            row[x] = i
            if is_promising(x):
                n_queens(x+1)

n_queens(0)
print(ans)

코드 설명 및 풀이법

백트래킹의 가장 기본 문제 중 하나인 N-Queen 문제이다.

 

처음에는 퀸이 놓인 위치를 기록해주기 위해서 2차원 배열을 사용하려 했으나 단순히 1차원 배열의 인덱스와 값을 통해서 위치를 기록해줄 수 있었다.

 

row[i] = j는 다음과 같이 해석될 수 있다.

 

"퀸을 [i, j] 위치에 놓겠다."

 

퀸의 위치를 정하고 나서는, 해당 위치에 퀸을 놓을 수 있는지 없는지 is_promising 함수를 통해서 판단한다.

 

퀸을 놓지 못하는 경우는 2가지이다.

 

1) 같은 열에 다른 퀸이 있는 경우

 

이 경우는, row라는 배열 안에 같은 값이 있는지 없는지를 확인하면 된다.

 

즉, row[i] = j라고 정의한 것에서 동일한 j값이 있는지 보겠다는 것이다. 퀸의 위치가 기록되는 값은 [i, j]라고 보면 이해하기 쉽다.

 

2) 왼쪽 대각선, 오른쪽 대각선에 다른 퀸이 있는 경우.

 

우리는 퀸을 맨 윗 행부터 차례로 채우고 있다.

 

따라서 대각선을 확인할 때 현재 i보다 큰 값들은 확인할 필요 없이 i보다 작은 곳, 즉 체스판의 위쪽만 확인하면 된다.

 

대각선에 위치한 퀸을 확인하기 위해서는 그들 간 인덱스의 관계를 활용하면 O(1)번만에 확인할 수 있다.

 

첫 번째로, 왼쪽 위 대각선의 값들을 살펴보자.

 

만약에 현재 퀸을 놓은 위치가 (3, 3)라고 가정하면, 왼쪽 대각선의 좌표는 각각 (2, 2), (1, 1), (0, 0)이 된다.

 

여기서, (3, 3)을 i와 j라고 하고, (2, 2)를 x1, y1, (1, 1)을 x2, y2, (0, 0)을 x3, y3이라고 해보자.

 

i에서 x1을 뺀 값과 j에서 y1를 뺀 값은 모두 1로 같다.

 

또한, i에서 x2를 뺀 값과 j에서 y2를 뺀 값은 모두 2로 같다.

 

세 번째 경우도 3으로 마찬가지로 동일하다.

 

 

두 번째로, 오른쪽 위 대각선 값들을 살펴보자.

 

동일하게 현재 퀸의 위치가 (3, 3)이라고 가정하면 오른쪽 대각선의 좌표는 (2, 4), (1, 5), (0, 6)이 된다.

 

마찬가지로 (3, 3)을 i, j로, (2, 4)를 x1, y1, (1, 5)를 x2, y2, (0, 6)을 x3, y3로 두고 i, j값에서 x와 y를 뺀 값을 살펴보면

 

(1, -1), (2, -2), (3, -3)이 된다.

 

이 두 가지 케이스를 일반화하여 식으로 정리하면 is_promising 함수가 된다.

 

만약 현재 퀸을 놓으려는 위치가 promising하다면, 다음 퀸을 놓기 위한 n_queens(i + 1)을 호출해주도록 해주고, 그렇게 타고타고 들어간 x가 최종 깊이인 n이 되면 모든 퀸을 놓았다는 것이 되므로 ans에 1을 추가해준다.

 

 

(추가 +)

해당 문제의 해당 코드는 Python으로는 통과가 안되고, pypy3로 제출 시 통과됩니다.

 

다만, 변수 선언 위치와 같은 사소한 것에 따라서도 통과 / 시간초과가 갈리기도 하는 말그대로 파이썬으로 통과하기 정말 빡빡한 문제로 보입니다.

 

동일한 코드에서도 어쩔 땐 통과하고 어쩔 땐 시간초과가 뜨기도 하더라구요.

 

이런 경우는 처음이라 저도 신기하네요. 여튼 이 점 참고 부탁드리며, 혹시 다른 더 좋은 방법이 있다면 댓글로 알려주시면 감사하겠습니다.

 

혹시나 참고하실 분 계실까 동일 로직의 자바 코드도 추가합니다.

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    static int N;
    static Scanner sc = new Scanner(System.in);
    static int ans;
    static List<Integer> row;

    static boolean isPromising(int x) {
        for (int i=0; i<x; i++) {
            if (row.get(x) == row.get(i) | Math.abs(row.get(x) - row.get(i)) == Math.abs(x - i)) {
                return false;
            }
        }

        return true;
    }

    static void nQueen(int x) {
        if (x == N) {
            ans++;
            return;
        }

        for (int i=0; i<N; i++) {
            row.set(x, i);
            if (isPromising(x)) {
                nQueen(x + 1);
            }
        }
    }

    public static void main(String[] args) {
        N = sc.nextInt();
        ans = 0;
        row = new ArrayList<>();
        for (int i=0; i<N; i++) {
            row.add(0);
        }

        nQueen(0);
        System.out.println(ans);

    }
}

 

저작자표시

'알고리즘 > 문제풀이' 카테고리의 다른 글

[백준] 1450번 냅색문제 - 파이썬(Python)  (0) 2021.10.01
[백준] 14502번 연구소 - 파이썬(Python)  (0) 2021.10.01
[백준] 1208번 부분수열의 합 2 - 파이썬(Python)  (0) 2021.09.30
[백준] 12865번 평범한 배낭 - 파이썬(Python)  (0) 2021.09.29
[백준] 2467번 용액 - 파이썬(Python)  (0) 2021.09.28
  1. 문제 (링크)
  2. 나의 풀이
  3. 코드 설명 및 풀이법
  4. (추가 +)
'알고리즘/문제풀이' 카테고리의 다른 글
  • [백준] 1450번 냅색문제 - 파이썬(Python)
  • [백준] 14502번 연구소 - 파이썬(Python)
  • [백준] 1208번 부분수열의 합 2 - 파이썬(Python)
  • [백준] 12865번 평범한 배낭 - 파이썬(Python)
SeongOnion
SeongOnion
서버는 꺼지지 않아요
SeongOnion
조무래기 코딩
SeongOnion
전체
오늘
어제
  • 분류 전체보기 (161)
    • 알고리즘 (81)
      • 이론 (8)
      • 문제풀이 (73)
    • 언어 (15)
      • Python (9)
      • JavaScript (1)
      • JAVA (5)
    • 데이터베이스 (5)
    • 프레임워크 (15)
      • Django (7)
      • Spring (8)
    • 그 외 공부 (35)
      • 운영체제 (1)
      • 자료구조 (14)
      • 네트워크 (5)
      • CS (2)
      • 기타 (5)
      • 트러블 슈팅 (8)
    • 프로젝트 (0)
    • 개발자취 (8)
    • 회고 (0)
    • 주저리주저리 (1)
    • 기타 (비개발) (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 파이썬
  • 알고리즘
  • spring
  • 회고
  • 웹
  • 에라토스테네스의 체
  • DP
  • DRF
  • 개발자
  • 이진탐색
  • 브루트포스
  • 트러블 슈팅
  • 장고
  • 코딩
  • 그리디알고리즘
  • 백준
  • 소수
  • BFS/DFS
  • 데이터베이스
  • 큐
  • 오픈소스
  • BFS
  • 자바
  • 스택
  • 정렬 알고리즘
  • 컨트리뷰트
  • 투 포인터 알고리즘
  • 프로그래머스
  • Django
  • 코딩테스트

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
SeongOnion
[백준] 9663번 N-Queen - 파이썬(Python)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.