N-queens

Updated:

C++

2468번 - 안전영역

문제

n*n 체스판 위에 동일한 행, 열, 대각선 상에 있지 않는 n개의 체스 말을 놓을 수 있는 지 출력하는 문제

백트래킹 공부를 위해 출처의 사이트를 보며 알고리즘을 짜보았습니다. 공부를 위해서는 윗 블로그 분이 훨~씬 정리 잘해놓으셨으니 저기로 가셔유

접근 방법 및 구현

queen을 놓을 좌표를 1차원 배열을 통하여 key, value 느낌으로 구현하였다. (1,1)~ (1,4)까지 탐색하며 (1,1) 에서 (2,1) ~ (2,4) 이렇게 한 단계씩 DFS로 탐색을 하는데! promising이란 함수를 통하여 더 이상 탐색 할 지 말지 결정한다. 이를 통해 Back Tracking을 구현하여 탐색 범위를 획기적으로 줄인다.

백트래킹의 제일 중요한 점은 깊이 우선 탐색을 하다, 유망성을 판단하는 것이다! 이는

boolean back trackin(현재 위치)
	if non-promising
		return false;
	else if 목표 지점에 도달 하였을 때
		return true;
	else
		상태 공간 트리의 현재 위치에서 자식 노드들을 순회한다. 

코드

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

int n;
int* col;
bool MyQueen(int);
bool promising(int);
void PrintQueen();
int main() {

	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cin >> n;
	//편의성을 위해 y축 1에서 시작하기 위해 실제 size를 1늘린다.
	col = new int[n + 1];

	MyQueen(0);

	return 0;
}

bool MyQueen(int level) {
	//들어온 좌표 위치가 유망한지(앞선 queen과 충돌을 하는지) 확인하며
	//충돌하면 false를 반환하여 x를 한단계 올린다.
	if (!promising(level)) {
		return false;
	}
	//n개의 queen이 모두 놓이면
	else if (level == n) {
		PrintQueen();
		//true를 반환하여 함수를 빠져나가도록 만든다.
		//만약 false 이면 다시 다음 i값으로 새로 함수를 시작한다.
		return true;
	}
	for (int i = 1; i <= n; i++) {
		col[level + 1] = i;
		if (MyQueen(level + 1)) {
			//true를 반환하면 함수를 빠져나가도록 만든다.
			return true;
		}
	}
	return false;
}

//유망한지, 유망하지 않은 지 확인한다.
//현재 해당하는 level의 아래 값들이, 즉 만약 3번째 행에서 값이 1, 2 번째 행의 queen이 충돌을 일으키지 않는 가를 확인한다.
bool promising(int level) {
	for (int i = 1; i < level; i++) {
		//만약 x 좌표 값이 같으면 queen 충돌이므로 false
		if (col[i] == col[level])
			return false;
		//각 좌표간의 y값의 차이와 x값의 차이가 같으면 대각선이므로 충돌
		else if(level - i == abs(col[i] - col[level]))
			return false;
	}
	return true;
	
}

void PrintQueen() {
	for (int i = 1; i <= n; i++) {
		cout << "(" << i << "," << col[i] << ")" << "\n";
	}
}

후기 및 개선할 점

후기: 백준의 Back Tracking문제를 풀기 위해 이론을 공부하였다. 이 전에 stack을 통하여 풀려고 노력을 하였으나 실패하였다. 이유는, level 3까지는 탐색한다 하지만 3에서 더 이상 갈 곳이 없으므로 1로 돌아와야 하는데 이 과정에서 visitied가 level1 단계로 돌아오지 못하는 문제를 해결하지 못하였다.