와챠의 우당탕탕 코딩 일기장
[백준]13-백트래킹/5-N-Queen/9663 풀이 JAVA 본문
문제
N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.
N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N < 15)
출력
첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.
풀이 1 (JAVA)
내가 이해하기 어려웠기 때문에... 추가 설명도 덧붙인다.
일단 퀸은 가로, 세로, 대각선으로 이동할 수 있다.
그래서 퀸끼리 서로 공격할 수 없게 하려면
● | |||
● | |||
● | |||
● |
이런 식으로 한 행에 하나의 퀸(●)이 들어가야 한다. (n=4)
n*n 체스판에는 총 n개의 행이 있어서 column 배열은 new int[n]으로 생성한다.
위 그림을 배열로 나타내면 {1, 3, 0, 2}가 된다.
이제 중요한 것은 index 위치에 퀸을 두어도 되는지 체크하는 방법이다.
1, 하나의 행에 하나의 퀸만 들어갔는지 체크하는 방법
-가로
column 배열 자체가 n개의 헹을 나타내기 때문에 딱히 필요 없다.
-세로
- column[index] == column[i]
위 코드에서 index(현재 퀸을 둔 위치)와 i의 column 값이 같다는 것을 그림으로 보면 이런 식이다.
● | |||
● | |||
● | |||
● |
위 그림은 column = {1, 3, 0, 1}을 나타내고,
column[0] == column[3]의 값이 1로 같다.
즉, 하나의 행(가로)에 하나의 퀸이 있지만, 세로(열)에 퀸이 있어서 공격할 수 있게 된다.
2, 대각선 방향에 퀸을 둘 수 있는지 체크하는 방법
- Math.abs(index - i) == Math.abs(column[index] - column[i])
● | |||
● | |||
● | |||
● |
위 그림은 column = {2, 3, 0, 2}를 나타낸다.
●부분인 column[0]과 column[2]는 대각선으로 마주보고 있다.
이를 체크하는 방법은 밑변과 높이가 같은지 확인하는 것이다.
아래 그림을 다시 표현하면 아래와 같다.
index | column[index] | |||
0 | 2 | |||
1 | 3 | |||
2 | 0 | |||
3 | 2 |
-밑변
- index - i
2 - 0 = 2
-높이
- column[index] - column[i])
2 - 0 = 2
●부분도 잘 체크할 수 있도록 절댓값을 씌워준다.
풀이 2 (JAVA)
이 풀이는 퀸을 둔 위치와 그 대각선 자리에 다른 퀸을 두지 못하게 상태를 바꿔놓는 방법을 쓰고 있다.
col[i], dig1[index + i] , dig2[n - index - i]가 모두 false이면 퀸을 놓을 수 있다는 뜻이다.
그래서 그 자리에 퀸을 놓고(col[i] = true)
퀸이 놓인 자리의 대각선(↗, ↘)을 true로 바꾸어(dig1[index + i] = dig2[n - index - i] = true)
다른 퀸을 놓을 수 없게 하는 것이다.
대각선은 왜 dig1[index + i], dig2[n - 1 - index - i] 이런 방법으로 구하는지는 다음과 같다.
1, 대각선(↗) 자리를 false로 바꾸기
dig1(↗)은 행 + 열의 값으로 알 수 있다.
행 + 열 | 0 | 1 | 2 | 3 |
0 | 0 | 1 | 2 | 3 |
1 | 1 | 2 | 3 | 4 |
2 | 2 | 3 | 4 | 5 |
3 | 3 | 4 | 5 | 6 |
0, 1, 2, 3, 4, 5, 6 숫자들이 곧 대각선(↗)이자 dig1의 인덱스가 된다.
만약 행 + 열(index + i)의 값이 3이었다면
dig1[3] = false가 되는데, 이는 위 그림의 3의 자리에 놓을 수 없게 되었단 의미가 된다.
2, 대각선(↘) 자리를 false로 바꾸기
dig2(↘)의 값은 n + 행 - 열로 알 수 있다. 여기서 n은 4이다.
n + 행 - 열 | 0 | 1 | 2 | 3 |
0 | 4 | 3 | 2 | 1 |
1 | 5 | 4 | 3 | 2 |
2 | 6 | 5 | 4 | 3 |
3 | 7 | 6 | 5 | 4 |
1, 2, 3, 4, 5, 6, 7 숫자들이 곧 대각선(↘)이자 dig2의 인덱스가 된다.
위와 같이 dig2의 인덱스가 곧 그 숫자가 써있는 대각선을 의미한다.
n = 4일 때, 대각선을 false로 바꿀 때 최대 숫자는 7이기 때문에
n * 2인 8로 넉넉히 dig 배열을 선언해준다.
이해하는데 하루가 꼬박 걸렸다^^
'코딩 일기장 > 백준' 카테고리의 다른 글
[백준]백트래킹/연산자 끼워넣기/14888 풀이 JAVA (0) | 2021.01.04 |
---|---|
[백준] 13-백트래킹/6-스도쿠/2580 풀이 JAVA (0) | 2021.01.03 |
[백준]13-백트래킹/4-N과 M(4)/15652 풀이 JAVA (0) | 2020.12.21 |
[백준]13-백트래킹/3-N과 M(3)/15651 풀이 JAVA (0) | 2020.12.21 |
[백준]13-백트래킹/2-N과 M(2)/15650 풀이 JAVA (0) | 2020.12.21 |