https://programmers.co.kr/learn/courses/30/lessons/12952
[문제 설명]
가로, 세로 길이가 n인 정사각형으로 된 체스판이 있습니다. 체스판 위의 n개의 퀸이 서로를 공격할 수 없도록 배치하고 싶습니다.
예를 들어서 n이 4인경우 다음과 같이 퀸을 배치하면 n개의 퀸은 서로를 한 번에 공격할 수 없습니다.
체스판의 가로 세로의 세로의 길이 n이 매개변수로 주어질 때, n개의 퀸이 조건에 만족 하도록 배치할 수 있는 방법의 수를 return하는 solution함수를 완성해주세요.
제한사항
- 퀸(Queen)은 가로, 세로, 대각선으로 이동할 수 있습니다.
- n은 12이하의 자연수 입니다.
입출력 예
n | result |
4 | 2 |
[풀이]
- "퀸은 가로, 세로, 대각선으로 공격할 수 있다"라는 말은 체스판에서 하나의 퀸에 해당하는 열과 행, 대각선 등이 비어있어야 한다는 것을 뜻함.
- n의 숫자가 크지 않으므로 재귀함수를 사용해도 됨.
- 열에 해당하는 배열에는 몇 번째 자리에 퀸이 배치됐는지 표현
- 행에 해당하는 배열에는 그 행이 지금 퀸이 있는지 없는지를 표현
- 대각선은 오른쪽 위에서 왼쪽 아래로, 왼쪽 위에서 오른쪽 아래로 오는 배열 선언 <- 중요
- 열에 해당하는 배열에는 [1,3,1,2,4]가 들어가 있을 것이고
- 행에 해당하는 배열은 [true, true, true, true, true]가 되어있을 것이다.
- 대각선 배열도 마찬가지로 모두가 true
- 우리는 대각선이 채워져 있는지 없는지를 판단하는 배열을 만들어야 하는데 처음부터 끝까지 대각선으로 탐색하는 건 구현도 어렵고 시간도 오래 걸린다. 하나의 규칙을 찾아보자.
-우리는 여기서 오른쪽 위에서 왼쪽 아래로 내려오는 대각선의 규칙을 찾을 수 있다. 즉,
- 오른쪽 위에서 왼쪽 아래로 내려오는 대각선의 규칙은 체스판[i+j] = false, true로 나눠질 수 있을 것이다.
- ex) i = 0, j = 0 -> 체스판[0] = true -> 0열, 0행의 대각선은 이미 꽉 차 있다.
- ex) i = 4, j = 2 -> 체스판[6] = false -> 체스판에 안에 6이 차있는 대각선은 비어있다.
- 왼쪽 위에서 오른쪽 아래로 내려오는 대각선의 규칙을 찾아보자.
- 바로 예를 들어보자 i=1, j=4와 i=0, j=3인 부분이 같은 대각선 라인에 있다 규칙은 i - j + (n-1) 같다.
- 이렇게 되면 저기 0부터 8, 즉 n*2 -1의 크기에 해당하는 boolean배열이 이 대각선들의 사용 가능/불가능을 파악할 수 있다.
자세한 건 코드의 전체적인 흐름을 보며 이해해보자!
[코드]
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
|
public class NQueen {
int count;
boolean[] checkRow; // 행 중복검사
boolean[] checkDiagonalR; // \방향 대각선
boolean[] checkDiagonalL; // /방향 대각선
int[] answer; // 각 열에 해당하는 퀸의 위치
public int solution(int n) {
answer = new int[n];
checkRow = new boolean[n];
checkDiagonalL = new boolean[n *2 -1];
checkDiagonalR = new boolean[n *2 -1];
count = 0;
set(0, n);
return count;
}
public void set(int i, int n) {
for(int j = 0; j < n; j++) {
if(!checkRow[j] && !checkDiagonalL[i+j] && !checkDiagonalR[i-j+n-1]) { //행이 비었고, 왼쪽, 오른쪽 대각선의 조건에 만족할 시.
answer[i] = j;
if(i == n-1) {
count++;
return;
}else {
checkRow[j] = checkDiagonalL[i+j] = checkDiagonalR[i-j+n-1] = true;
set(i+1, n);
checkRow[j] = checkDiagonalL[i+j] = checkDiagonalR[i-j+n-1] = false;
}
}
}
}
|
cs |
느낀 점 : Queen문제를 처음 풀어본다. 글씨로 적고 구상을 해봐도 잘 안 풀리길래 예전에 사놓았던 책을 보며 공부해서 머릿속에 담고 혼자 문제를 풀어봤다. 이해가 잘 된 것 같아서 좋다.
'코딩테스트 > 프로그래머스 level 3' 카테고리의 다른 글
[프로그래머스 level_3] 기지국 설치 for JAVA (0) | 2020.05.12 |
---|---|
[프로그래머스 level_3] 배달 for JAVA (0) | 2020.05.09 |
[프로그래머스 level_3] 최고의 집합 for JAVA (0) | 2020.05.06 |
[프로그래머스 level_3] 줄 서는 방법 for JAVA (1) | 2020.05.06 |
[프로그래머스 level_3] 야근 지수 for JAVA (0) | 2020.05.05 |