
백트래킹 알고리즘의 심화버젼...
백트래킹은 여러 케이스를 다 고려하여서, 정답이 되는 것을 찾기에 알맞는 알고리즘이다.
앞 서 N과 M에 대해서는, 알맞는 수 를 찾기보다는 그냥 맞춰서 출력을 하는 그런 방식으로 쓰였다.
더 나아가서 N-Queen은 알맞는 위치를 수학적으로 고려하여, 세는 그런 문제가 되겠다.
혼자서 생각하기에는 너무 어려워서 역시나, 짖는개님의 아티클을 참고하여 해결해보았다.

퀸은 상, 하, 좌, 우, 대각선 모든 방향으로 다 이동할 수 있다.
그렇기에 퀸들을 놓기 위해서는 제한해야하는 케이스를 몇가지 생각할 수 있다.
그렇기에 이 세가지 조건에 부합하는 케이스에 맞는 자리에 '퀸'들을 배치할 수 있는 것이다.
퀸은 같은 행에 존재할 수 없으므로, 각 행에 대해서 퀸이 놓여질 자리를 구분할 필요는 없지만,
같은 열과, 대각선 방향으로의 문제를 고려해야 한다.
같은 열을 구분하는 방법은 간단하다
코드에서 2차원 배열로 구분한, N x N 정사각형이기에 좌표들이 [x][y]라고 한다면
y값이 같으면, 같은 열에 존재한다고 생각할 수 있다.
그리고 다음은 대각선들에 퀸이 올 수 있는지를 판단하는, 대각선의 문제다
대각선은 두가지 종류의 대각선이 생길 수 있는데,
첫번째는 오른쪽 위로 향하는 대각선
또 하나는 오른쪽 아래로 향하는 대각선 이다.
앞서 풀었던 백트래킹 문제와 같이,
isused배열을 이용하여 위의 조건에 맞춰서, 그 자리가 이용이 되었는지 여부를 판단하여 재귀로 문제를 해결해나가면 되겠다.
일단 세가지 배열을 만들어 놓아야한다.
isused_y = [False] * N 열의 위치관계에 대한 배열isused_x_pl_y = [False] * (2*N-1) 오른쪽 위로 향하는 대각선에서의 위치관계에 대한 배열isused_x_mi_y = [False] * (2*N-1) 오른쪽 아래로 향하는 대각선에서의 위치관계에 대한 배열만약 N = 4 라면, 만들어지는 정사각형은 인덱스가
이런식으로 2차원배열 형태의 인덱스로 표현 가능하다.
같은 열에 퀸이 존재 하는지는 2차원 배열에서 두번째 요소()가 같은지만 확인한면 된다.
오른쪽 위로 향하는 대각선에 대해서는 인덱스의 두 합()이 같은 애들을 한 선 위에 있다라고 생각할 수 있다.
예를 들어, 과 은 합이 1인 선 위에 있는 것으로 생각할 수 있고,
과 , 또한 합이 2인 선 위에 있는 것으로 생각할 수 있다.
x-y+N+1 로 구성해주기로 하자.N = 문제에서 입력을 받는 수cnt = 퀸이 놓아질 수 있는 케이스를 세는 변수isused_y = 같은 열에 있는지 확인하기 위한 배열isused_x_pl_y = 오른쪽 위로 가는 대각선 사용에 대한 배열isused_x_mi_y = 오른쪽 아래로 가는 대각선 사용에 대한 배열cnt를 전역 변수로 사용하여, 바깥 쪽에서 변경이 가능하도록 선언해주고, 재귀를 이용하여 점점 늘려나가며, 퀸을 다 놓으면 cnt를 하나 늘려준다.def func(cur):
global cnt
if cur == N:
cnt += 1
return
for i in range(N):
if isused_y[i] or isused_x_pl_y[i+cur] or isused_x_mi_y[cur-i+N-1]:
continue
isused_y[i] = True
isused_x_pl_y[i+cur] = True
isused_x_mi_y[cur-i+N-1] = True
func(cur+1)
isused_y[i] = False
isused_x_pl_y[i+cur] = False
isused_x_mi_y[cur-i+N-1] = False
반복을 시행하면서, 조건을 통해 그 자리에 놓아도 될지 안될지를 판단한다
if isused_y[i] or isused_x_pl_y[i+cur] or isused_x_mi_y[cur-i+N-1]:
만약 하나라도 놓여져있다면, continue를 통해서 아래 코드를 점프한다.
아니라면, 그 인덱스를 True로 만들어서 열, 대각선에 이미 사용되고 있다를 명시해주고
다음 재귀로 넘어간다.
그리고 나서는 이제 사용이 완료되면, 해당 인덱스들을 다 False로 바꾸어줘서 사용하지않음을 명시해준다.
앞서 풀었던, 해당하는 수열을 다 조사하는 것과 마찬가지로 백트래킹 알고리즘을 이용해서 풀어봤는데, 정말 사람들은 똑똑하구나 생각하게 되었다.
어느 정도 감은 잡혀가지만, 이 백트래킹 알고리즘에서 중요한건 과연 해를 어떤식으로 판단할 것인가가 제일 중요한 것 같다.
이 N-Queen 문제도 해를 저런식으로 판단하는 것을 바로 생각해내는건 처음 접하는 개발자들에게는 많이 힘들 것 같다.
백트래킹 문제들의 유형을 보면서, 다른 사람들의 코드를 많이 참고하여서 해를 판단하는 방법에 대해 고민하고 또 고민해야 할 것 같다.
아, 그리고 참 python3 로 제출하면 시간 초과 난다.
pypy3로 제출하자
