ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SWEA] 2806 - N-Queen
    programing/Algorithm 2019. 10. 29. 19:02

    안녕하세요, Einere입니다.

    (ADblock을 꺼주시면 감사하겠습니다.)


    이번 포스트에서는 삼성 SW Expert Academy의 2806번 문제인 N-Queen에 대해 알아보도록 하겠습니다.

     

     

    회의 시간 : 2019.11.03 13:00 ~ 15:00

    회의 장소 : 강남역 SG스터디룸

     

     

    접근 방법

    N-Queen 문제는 백 트래킹의 대표적인 문제입니다. 알고리즘 수업때 한번쯤 배우고 지나갑니다.

    제가 생각하는 키 포인트는 다음과 같습니다.

    • 백 트래킹 : 퀸을 특정 위치에 놓아 보고, 조건에 맞지 않다면 퀸을 치우고 다른 자리에 놓아 봅니다.
    • 퀸을 놓을 위치 : 문제에서 퀸들은 서로를 공격할 수 없어야 합니다. 즉, 특정 위치가 안전한 자리인지 확인해야 합니다.

    위 두 키 포인트를 위해, column라는 자료구조가 필요합니다. column은 각 행마다 놓여진 퀸의 열을 저장합니다. 예를 들어 columns = [2, 3, 1, 2]는 (1, 2), (2, 3), (3, 1), (4, 2)에 퀸이 놓여있다는 뜻입니다.

     

     

    백트래킹

    백트래킹은 다양하게 구현할 수 있습니다만, 해당 문제에서는 단순히 이전 상태를 새로운 상태로 덮어쓰는 방식으로 백트래킹을 구현하겠습니다.

     

     

    체스에서 퀸은 8방향으로 거리 제한 없이 이동할 수 있습니다. 이것을 이용해 안전한 자리인지 확인하는 방법은 크게 두가지로 나뉩니다.

    • 해당 행에 다른 퀸이 존재하는지 확인합니다.
    • 해당 열에 다른 퀸이 존재하는지 확인합니다.
    • 이전에 배치한 퀸의 대각선상에 존재하는지 확인합니다. 이는 두 퀸을 이용해 직각 삼각형을 그렸을 때, 밑변과 높이가 동일한 지 확인하면 됩니다.

     

     

    풀이 코드 (java)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
     
    public class Solution {
        private int testCaseNumber;
        private int[] Ns;
        private int[] cols;
        private int count;
     
        public void main() {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     
            try {
                testCaseNumber = Integer.parseInt(br.readLine(), 10);
                Ns = new int[testCaseNumber];
                for(int i = 0; i < testCaseNumber; i++) {
                    Ns[i] = Integer.parseInt(br.readLine(), 10);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
     
            for (int i = 0; i < testCaseNumber; i++) {
                cols = new int[Ns[i] + 1];
                queen(0, Ns[i]);
                System.out.println(String.format("#%d %d", i+1, count));
                count = 0;
            }
        }
     
        // 임의의 열에 퀸을 배치한 row에 대해, promising한지 검사합니다
        private void queen(int row, int N) {
            // 배치된 퀸이 다른 퀸과 충돌하는 경우
            if (!promising(row)) return;
     
            // 다른 퀸과 충돌하지 않으면서, 마지막 행에 퀸을 배치한 경우
            if (row == N) {
                count++;
            } else {
                for (int i = 1; i <= N; i++) {
                    // 현재 행까지는 배치가 완료되었으며, 다음 행에 임의로 배치 후 promising한지 검사합니다
                    cols[row + 1] = i;
                    queen(row + 1, N);
                }
            }
        }
     
        // 해당 함수가 호출된 row에 대해, row-1번째 퀸까지는 정상적으로 배치되었음을 전제로 합니다.
        // 즉, row번째 퀸과 그 이전의 퀸들과 충돌 여부만 검사하면 됩니다.
        private boolean promising(int row) {
            // 0번째 행에는 퀸을 배치하지 않으므로, true를 반환합니다
            if (row == 0) return true;
     
            for (int i = 1; i < row; i++) {
                // 같은 열에 다른 퀸이 존재하는지 검사합니다.
                if (cols[row] == cols[i]) return false;
                // 대각선에 다른 퀸이 존재하는지 검사합니다.
                else if (row - i == Math.abs(cols[row] - cols[i])) return false;
            }
            return true;
        }
    }

    그런데 제출을 해보면 런타임 에러(메모리 관련)이 뜨네요..

    'programing > Algorithm' 카테고리의 다른 글

    [BJ] 2805 - 나무 자르기  (0) 2019.11.09
    [SWEA] 1868 - 파핑파핑 지뢰찾기  (0) 2019.11.01
    [BJ] 17471 - 게리맨더링  (0) 2019.10.20
    [Algorithm] 조합 (Combination)  (0) 2019.10.19
    [BJ] 13460 - 구슬 탈출 2  (0) 2019.10.12

    댓글

Designed by black7375.