알고리즘/백준

공부 222일차: 백준 9663번 N-Queen 자바 java

김발자~ 2023. 3. 9. 23:01
반응형

9663 N-Queen

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

 

9663번: N-Queen

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

www.acmicpc.net

 

 

 

 


백준 9663번 문제 N-Queen


문제


 

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
10 초 128 MB 86866 41771 27108 46.790%

문제

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.

N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N < 15)

출력

첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.

예제 입력 1

8

예제 출력 1

92

힌트

 

 

 


과정 생각해보기 & 오답


 

체스 규칙을 몰라서, 퀸끼리 서로 공격할 수 없게 만드는 조건이 무엇인지 알아야 했다

이 기사를 확인해 보니 각각 다른 가로줄, 세로줄, 대각선에 있어야 한다는 게 조건이다

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
 
public class Main {
 
    static int n, cnt;
    static int[][] board;
    static boolean[][] visited;
    static int[] dx = {-1-111};
    static int[] dy = {-11-11};
    
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
        n = Integer.parseInt(br.readLine());
        board = new int[n][n];
        visited = new boolean[n][n];
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                visited = new boolean[n][n];     // 초기화
                dfs(0, i, j);
            }
        }
        
        bw.write(cnt+"");
        bw.flush();
        bw.close();
        br.close();
    }
 
    static void dfs(int depth, int x, int y) {
        if(depth == n) {    // 끝까지 다 돌다 == 경우의 수 중 하나
            cnt++;
            return;
        }
 
        board[x][y] = 1;    // 퀸 표시
        
        // 같은 가로줄, 세로줄 방문 불가
        for(int i = 0; i < n; i++) {
            visited[x][i] = true;
            visited[i][y] = true;
        }
        
        // 대각선 방문 불가
        for(int i = 0; i < 4; i++) {
            int X = x+dx[i];
            int Y = y+dy[i];
            
            if(X < 0 || X > n-1 || Y < 0 || Y > n-1) {
                continue;
            }
            
            visited[X][Y] = true;
        }
        
        for(int i = 1; i < n; i++) {
            for(int j = 1; j < n; j++) {
                int X = x+i;
                int Y = y+j;
                
                // 범위 밖
                if(X < 0 || X > n-1 || Y < 0 || Y > n-1) {
                    continue;
                }
                
                
                if(!visited[X][Y]) {
                    board[X][Y] = 1;    // 퀸 표시
                    dfs(depth+1, X, Y);
                }
            }
        }
    }
}
 
cs

인접한 대각선들만 피하면 되는 걸로 착각해서 썼다가 틀린 코드. 물론 그것 말고도 문제가 많다

 

열의 차와 행의 차가 같으면 같은 대각선에 있는 것이다

아래 표로 보자

0,0 0,1 0,2 0,3
1,0 1,1 1,2 1,3
2,0 2,1 2,2 2,3
3,0 3,1 3,2 3,3

빨간 색깔로 표시한 부분이 대각선인데, 행과 열의 차의 절댓값이 모두 1임을 알 수 있다

대각선이 아닌 파란 색깔은 1,2와 비교했을 때 차의 절댓값이 각각 0, 1이 나온다 

 

 

 


정답 인정 코드


 

1. 1차원 배열 이용 (이 블로그 참고)

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
 
public class Main {
 
    static int n, cnt;
    static int[] arr;
    
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
        n = Integer.parseInt(br.readLine());
        arr = new int[n];
        
        dfs(0);
        bw.write(cnt+"");
        bw.flush();
        bw.close();
        br.close();
    }
 
    static void dfs(int depth) {
        if(depth == n) {    // 끝까지 다 돌다 == 경우의 수 중 하나
            cnt++;
            return;
        }
 
        for(int i = 0; i < n; i++) {
            arr[depth] = i;
            
            if(isPossible(depth)) {
                dfs(depth+1);
            }
        }
    }
    
    static boolean isPossible(int col) {
        for(int i = 0; i < col; i++) {
            if(arr[col] == arr[i]) {    // 같은 행
                return false;
            }else if(Math.abs(col-i) == Math.abs(arr[col]-arr[i])) {    // 대각선
                return false;
            }
        }
        
        return true;
    }
}
 
cs

훨씬 간단

 

2. 2차원 배열 이용

 

 

 


1차원 배열로 풀다니 이런 걸 어떻게 생각하지?!

그래도 2차원 배열로도 풀어보고 싶어서 나중에 재도전 예정..

반응형