Algorithm/Backtracking

BOJ#9663 N-Queen

밤이2209 2016. 11. 11. 15:28

BOJ#9663 N-Queen


* 문제

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



* 풀이


유명하면서도 어려운 문제입니다.


Queen을 1개~N개까지 배치하면서, 잘못 배치한 경우 되돌아가서 다른 시도를 해봐야 합니다. 

따라서 backTracking을 이용합니다.


주의할 점


0. Queen

Queen은 상하좌우, 대각선 모두 이동할 수 있습니다.




1. 꼭 행렬로 map을 만들 필요가 없습니다.

보통 map 행렬을 만든 후 -1, 0, 1등의 숫자를 이용해

배치할 수 있는 곳과 아닌 곳을 표시하고, 이 정보를 기반으로 다음 행동을 결정하는데


이 경우 불필요한 리소스와 시간이 소요됩니다.




2. Queen은 N개 이므로 행(row) 1개당 Queen 1개가 배치됩니다.

 = 각 행마다 Queen이 배치될 Column 결정하는 문제


따라서 int[] column = new int[N] 을 만들어줍니다.


column[0] = 0행에서 0번째 queen이 위치한 column

column[1] = 1행에서 1번째 queen이 위치한 column

column[2] = 2행에서 2번째 queen이 위치한 column

...

column[N-1] = N-1행에서 N-1번째 queen이 위치한 column




3. Queen을 (targetRow, targetCol)에 배치할 때, 해당 위치가 안전한지 판단해야 합니다.

특히 대각선의 경우 어떻게 간단히 판별할지 고민이 필요합니다.


1) 열 검사

이전에 위치한 Queen들과 같은 열에 위치하면 안됩니다.


for ( row = 0 ; row < targetRow ; row++) {


column[row] == targetCol ?

}


2) 대각선 검사

이전에 위치한 Queen들과 대각선에 위치하면 안됩니다.


for ( row = 0 ; row < targetRow ; row++) {


targetRow - row == Math.abs(targetCol - column[row] ?

}



3) 행 검사

행 검사는 할 필요가 없습니다. 위에서 말했듯이 행마다 Queen이 1개씩 위치하기 때문입니다.



Solution#1 (시간 초과)

- ArrayList에 int가 아닌 Integer 객체를 생성해서 넣어줘야 합니다. 그래야 ArrayList에서 원하는 Object를 삭제할 수 있습니다.

- (Line 44) row++가 아니라 row+1을 해줘야 합니다. row++을 하면 다음 Iteration에서 row값이 변경된채로 진행됩니다.

- (Line 45) 다음 Iteration을 위해 변경사항을 원복해줍니다.




Solution#2 (메모리 : 17440 KB , 시간 : 6540 MS)

- 시간 초과 때문에 ArrayList를 버리고 간단하게 isSafePlace()함수를 구현했습니다.

- (Line 57) loop 반복 조건에서 row < N이 아니라 row < targetRow를 해주면 불필요한 loop를 피할 수 있습니다.





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

BOJ#2580 스도쿠  (0) 2017.03.23
BOJ#1405 미친 로봇  (0) 2017.03.16
BOJ#2661 좋은수열  (0) 2017.03.16