ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 9663) N-Queen (골드.4)
    알고리즘/백준 2022. 7. 17. 18:37

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

     

    9663번: N-Queen

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

    www.acmicpc.net

     

     

     

    문제의 조건은 다음과 같으며 백트래킹을 이용하여 퀸을 놓을 수 있는 모든 경우의 수를 찾는 것이다. 

    1) 같은 열에 퀸이 없을 것

    2) 같은 행에 퀸이 없을 것 

    3) 퀸의 대각선(오른쪽, 왼쪽)으로는 다른 퀸을 위치하지 않을 것 

     

     

    이 문제는 python3로 풀때 계속해서 시간초과가 났기 때문에 해결방법을 찾지 못했다 😭 

    두번 모두 pypy로는 성공하였다 😭

     

    내가 처음에 푼 코드는 다음과 같다. 이것이 다음에 확인한 코드보다 메모리도 적게 사용하고 시간도 더 빨랐다. 

    행과 열, 오른쪽 대각선, 왼쪽 대각선 정보를 담을 배열들을 만들고 해당 부분에 놓을 수 있는지를 확인할 수 있도록 하였다. 

    여기서 대각선을 설명하자면 오른쪽 대각선이 같은 부분들언 행+열의 값이 같은 값을 띄며 [0, 1, 2, 3, ... 2n-1]까지의 값을 같는다.

    왼쪽 대각선의 경우 i-j의 값이 같은 같은 값들이며 여기서 값이 [-(n-1), -(n-2), ...,0, 1, 2, ..., n-1]의 모양새를 띄기 때문에 인덱스를 사용하기 위해서 n-(i-j)-1을 사용하도록 하였다. 

    global n, board, check_row, check_col, check_right_diag, check_left_diag, answer
    n = int(input())
    answer = 0
    board = [[False]*n for _ in range(n)]
    
    check_row = [False]*n
    check_col = [False]*n
    check_right_diag = [False]*(2*n-1)
    check_left_diag = [False]*(2*n-1)
    
    
    def isPossiblePosition(i, j) :
        global n, board, check_row, check_col, check_right_diag, check_left_diag
        if board[i][j] == True:
            return False
        if check_col[j] == True:
            return False
        if check_row[i] == True:
            return False
        if check_right_diag[i+j] == True:
            return False
        if check_left_diag[n-(i-j)-1] == True:
            return False
        return True
    
    def play_queen(i, j, isPut):
        global n, board, check_row, check_col, check_right_diag, check_left_diag
        board[i][j] = isPut
        check_row[i] = isPut
        check_col[j] = isPut
        check_right_diag[i+j] = isPut
        check_left_diag[n-(i-j)-1] = isPut
    
    def find_case(depth):
        global answer, board, n, check_row, check_col, check_right_diag, check_left_diag
        if depth == n:
            answer += 1
            return 
        for col in range(n):
            if isPossiblePosition(depth, col):
                play_queen(depth, col, True)
                find_case(depth+1)
                play_queen(depth, col, False)
        return 
    
    find_case(0)
    
    print(answer)

     

     

    코드가 생각보다 길고 복잡해져 검색해보니 행-행 = 열 - 열 이면 같은 대각선에 있음 을 이용하도록 변경하였다. 여기서 col에 존재하는 가 는 visited배열을 이용해서 해당 column에 있는지 확인하도록 하였다. 

    global n, board, check_row, answer
    n = int(input())
    answer = 0
    board = [0]*n
    visited = [False]*n
    
    def isPossiblePosition(depth) :
        global n, board
        for row in range(depth):
            if abs(depth-row) == abs(board[depth]- board[row]):
                return False
        return True
    
    def find_case(depth):
        global answer, board, n
        if depth == n:
            answer += 1
            return 
        for col in range(n):
            if visited[col] == False:
                board[depth] = col
                if isPossiblePosition(depth) :
                    visited[col] = True
                    find_case(depth+1)
                    visited[col] = False
        return 
        
    find_case(0)
    
    print(answer)

     

     

     

    '알고리즘 > 백준' 카테고리의 다른 글

    백준 7569) 토마토 (골드.5)  (0) 2022.07.17
    백준 7576) 토마토 (골드.5)  (0) 2022.07.17
    백준 2580) 스도쿠 (골드.4)  (0) 2022.07.16
    백준 14501) 퇴사 (실버.3)  (0) 2022.07.15
    백준 14889) 스타트와 링크 (실버.2)  (0) 2022.07.14
Designed by Tistory.