[C++] BOJ #9663 N-Queen
Posted on 2022. 01. 26
문제
N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.
N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.
입력
- 첫째 줄에 N이 주어진다. (1 ≤ N < 15)
출력
- 첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.
해결방법 및 소스코드
- Brute Force하게 재귀호출을 이용한 백트래킹 방법을 이용하였다.
- 이 문제를 처음 C로 풀었었을 때는 체스판을 2차원 배열로 만들어서 복잡하게 해결했었는데, 이번에는 1차원 배열만으로 해결했다.
- 굳이 복잡하게 2차원 배열을 만들 필요 없이, 1차원 배열의 인덱스(
i
)를 행(level), 각 원소(chessBoard[i]
)를 열로 생각하면 된다. - 1차원 배열의 인덱스도 적절하게 활용하면 코드를 쉽고 간단하게 짤 수 있다는 것을 알게 해 준 문제였다.
#include <iostream>
using namespace std;
int N;
//checkPosition: 현재 칸에 퀸을 놓을 수 있는지를 판단한다.
//curlevel: 현재 퀸을 놓으려는 행번호
//curcol: 현재 퀸을 놓으려는 열번호
int checkPosition(int chessBoard[], int curlevel, int curcol)
{
//현재 놓으려는 칸의 열이 이전 퀸들과 중복이 있다면 놓을 수 없다.
for (int i = 0; i < curlevel; i++)
{
if (chessBoard[i] == curcol)
return 0;
}
//현재 놓으려는 칸의 이전 퀸들의 대각위치에 있다면 놓을 수 없다.
//이전칸 (i, chessBoard[i])과 현재 놓으려는 칸 (curlevel, curcol)에서 x좌표의 차와 y좌표의 차가 같으면 대각위치이다.
//즉, 두 점을 이은 직선의 기울기의 절대값이 1이면 놓을 수 없다.
for (int i = 0; i < curlevel; i++)
{
if (abs(curlevel - i) == abs(curcol - chessBoard[i]))
return 0;
}
return 1;
}
void placeQueen(int chessBoard[], int level, int &count)
{
//탈출 조건(count 증가 조건)
if (level == N)
count++;
//chessBoard[현재레벨][x]에 퀸을 놓을 수 있는지 검사
for (int x = 0; x < N; x++)
{
//만약 퀸을 놓을 수 있다면, 퀸을 놓고 다음 단계로 이동.
if (checkPosition(chessBoard, level, x))
{
chessBoard[level] = x;
placeQueen(chessBoard, level + 1, count);
}
}
}
int main()
{
cin >> N;
//level: 체스판의 재귀 깊이
//count: 구하는 경우의 수를 카운트
int level = 0;
int count = 0;
//체스판 배열에서 각 인덱스는 '행', 각 원소는 '열'을 의미한다.
int chessBoard[N];
placeQueen(chessBoard, level, count);
cout << count;
}