N-Queens 문제는 작년에 풀다가 포기했던 기억이 나고 책에도 마침 나오길래 다시 풀어보았다.
그 때 당시의 풀이를 생각해보면 접근부터가 잘못되었던 것을 이제야 알게되었다.
그 당시에는 문제를 분할정복을 적용하여서 풀려고 했었다. 그런데 지금 와서 다시 생각해보니 완전 헛발을 짚은 것이다...
서론이 길었는데 코드부터 보여드리겠습니다.
#include <iostream>
using namespace std;
int cnt = 0, map[15][15], col[15], across1[50], across2[50], n;
void queens(int y)
{
if(y == n) // n-1행까지 다 돌았으면 횟수를 추가하고 리턴
{
cnt++;
return;
}
for(int x = 0; x<n; x++){ // 열을 반복
if(col[x] || across1[x+y] || across2[x-y+n-1]) continue;
//같은 행, 같은 기울기의 대각선이 존재한다면 continue
col[x] = 1;
across1[x+y] = 1;
across2[x-y+n-1] = 1;
queens(y+1); // 다음 행 값
col[x] = 0;
across1[x+y] = 0;
across2[x-y+n-1] = 0;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> n;
queens(0);
cout << cnt;
return 0;
}
이 문제를 정확하게 설명하면
행마다 단 하나의 퀸을 배치하되, 그 퀸이 이전 단계에 배치된 퀸을 공격할 수 없도록 배치하는 것이다. 만약 nXn 이라면 n개의 퀸을 배치하면 그 때 하나의 해를 구한 것이다.
이 때 이전 단계의 배치된 퀸을 공격할 수 없도록 하기 위해 같은 열, 두 대각선에 대한 번호를 부여하여 가능성을 제거해야 한다.
0 | 1 | 2 | 3 |
0 | 1 | 2 | 3 |
0 | 1 | 2 | 3 |
0 | 1 | 2 | 3 |
col[] 배열은 같은 열이면 같은 번호가 부여된다.
0 | 1 | 2 | 3 |
1 | 2 | 3 | 4 |
2 | 3 | 4 | 5 |
3 | 4 | 5 | 6 |
across1[] 배열
3 | 4 | 5 | 6 |
2 | 3 | 4 | 5 |
1 | 2 | 3 | 4 |
0 | 1 | 2 | 3 |
across2[] 배열
이런 식으로 같은 번호가 배정되는 규칙이 있다.
따라서 같은 수가 부여된다면 그 위치에는 배치될 수 없기에 해를 구할 수 있다.
하지만 백트랙킹은 브루트포스의 방법을 적용한 것으로 모든 경우의 수를 하면서 가지치기를 진행하는 것으로 n이 증가할 때 마다 탐색이 급격하게 느려진다.
실제로 n이 27에 달하면 경우의 수는 컴퓨터 클러스터를 사용하여야 한다.
'컴퓨터과학(CS) > 알고리즘' 카테고리의 다른 글
최대공약수(GCD), 최소공배수(GCM) - 유클리드 호제법 (0) | 2021.09.06 |
---|---|
버블정렬 (0) | 2021.08.31 |
최대 부분 배열 합 - 백준 10211 (0) | 2021.08.30 |
시간 복잡도 (0) | 2021.08.26 |
순열(재귀) (0) | 2021.08.20 |