πŸ“ Coding Test Study/Algorithm Problem

[C++][Baekjoon][Backtracking] 9663번 N-Queen 풀이

ibelieveinme 2021. 8. 5. 10:39
728x90

λ°±νŠΈλž˜ν‚Ή(Back Tracking)
- μ™„μ „ νƒμƒ‰μ—μ„œ λΆˆν•„μš”ν•œ λΆ„κΈ°(Branch)λ₯Ό κ°€μ§€μΉ˜κΈ°(Pruning)
- ν•΄λ₯Ό μ°ΎλŠ” 도쀑 ν•΄κ°€ μ•„λ‹ˆμ–΄μ„œ λ§‰νžˆλ©΄, λ˜λŒμ•„κ°€μ„œ λ‹€μ‹œ ν•΄λ₯Ό μ°Ύμ•„κ°€λŠ” 기법

 

즉, Backtrackingμ΄λž€, κ°„λ‹¨ν•˜κ²Œ 말해 brute-force(μ „λΆ€ 일일히 λ‹€ ν•΄λ³΄λŠ” 것)방법을 μˆ˜ν–‰ν•˜μ§€λ§Œ ν•œμ • ν•¨μˆ˜(bounding function)을 μ΄μš©ν•΄ 경우의 수λ₯Ό μ€„μ—¬λ‚˜κ°€λŠ” 방법을 λ§ν•œλ‹€.

 

[κ΄€λ ¨λ¬Έμ œ]

 

9663번: N-Queen

N-Queen λ¬Έμ œλŠ” ν¬κΈ°κ°€ N × N인 체슀판 μœ„μ— ν€Έ N개λ₯Ό μ„œλ‘œ 곡격할 수 μ—†κ²Œ λ†“λŠ” λ¬Έμ œμ΄λ‹€. N이 μ£Όμ–΄μ‘Œμ„ λ•Œ, 퀸을 λ†“λŠ” λ°©λ²•μ˜ 수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

www.acmicpc.net

[풀이]

1차원 ν–‰μ—΄ int queen_col[15] μ„ μ΄μš©ν•΄μ„œ ν€Έμ˜ μœ„μΉ˜λ₯Ό μ €μž₯ν•œλ‹€.
이 λ•Œ, queen_col의 indexλŠ” 행을 μ˜λ―Έν•˜κ³ , μ•ˆμ˜ 값듀은 열을 μ˜λ―Έν•œλ‹€.

ν€Έμ˜ μœ„μΉ˜λ₯Ό μ €μž₯ν•  λ•Œ λ‹€μŒ 2개의 쑰건문을 ν™œμš©ν•΄μ„œ queen을 놓을 수 μžˆλŠ”μ§€ μ—†λŠ”μ§€λ₯Ό νŒλ‹¨ν•œλ‹€.

 

    1. queen_col[col] == queen_col[row]
        0 1 2 3 <- 행을 의미
        γ…γ…γ…γ… <- μ—΄μ˜ μœ„μΉ˜λ₯Ό 의미

 

queen은 같은 μ—΄/ν–‰ 상에 놓이면 μ•ˆλ˜λ―€λ‘œ
col을 +1 ν•΄μ£Όλ©° λŒλ©΄μ„œ queen_col에 같은 값이 μ €μž₯λ˜μ–΄ μžˆλŠ”μ§€λ₯Ό ν™•μΈν•œλ‹€.(같은 값이 μžˆλ‹€λ©΄, 같은 열에 μžˆλ‹€λŠ” μ˜λ―Έλ‹ˆκΉ)

 

    2. abs(queen_col[row] - queen_col[col]) == (row - col)
        0 1 2 3 <- 행을 의미
        ㅁㅁㅁㅁ <- μ—΄μ˜ μœ„μΉ˜λ₯Ό 의미

 

queen_col[]λŠ” queen_col에 λ“€μ–΄μžˆλŠ” κ°’μ΄λ―€λ‘œ 열을 μ˜λ―Έν•˜κ³ 
row, col은 inxexμ΄λ―€λ‘œ 행을 μ˜λ―Έν•œλ‹€.
ν˜„μž¬μ’Œν‘œμ™€ λŒ€κ°μ„  μ’Œν‘œμ˜ μ—΄μ˜ 차와 ν–‰μ˜ μ°¨κ°€ κ°™λ‹€λ©΄ λŒ€κ°μ„ μ— μœ„μΉ˜ν•œ 것을 μ˜λ―Έν•œλ‹€.

 

예λ₯Ό λ“€μ–΄ ν˜„μž¬ μ’Œν‘œλŠ” 0,0 이고, ν˜„μž¬ μ’Œν‘œμ˜ λŒ€κ°μ„  μ’Œν‘œλŠ” 1,1 일 λ•Œ,
각각 열은 μ—΄κ°’λŒ€λ‘œ, 행은 ν–‰κ°’λŒ€λ‘œ λΉΌλ©΄ 0 - 1 == 0 - 1 이 성립함을 μ•Œ 수 μžˆλ‹€.

 

[μ½”λ“œ]

#include <iostream>
using namespace std;

void N_Queen(int);

int N;//λ¬Έμ œμ—μ„œ μ£Όμ–΄μ§€λŠ” κ²Œμž„νŒμ˜ 크기
int queen_col[15];//ν€Έμ˜ μ—΄μœ„μΉ˜λ₯Ό μ €μž₯ν•  λ°°μ—΄(queen_col의 μΈλ±μŠ€λŠ” μžμ—°μŠ€λ ˆ 행을 μ˜λ―Έν•˜κ²Œ λœλ‹€)
int answer;//퀸을 놓을 수 μžˆλŠ” 개수

bool isEmpty(int);//ν–‰, λŒ€κ°μ„ μ— Queen이 μžˆλŠ”μ§€ νƒμƒ‰ν•˜λŠ” ν•¨μˆ˜

int main() {
	cin >> N;

	N_Queen(0);//1. 0ν–‰λΆ€ν„° 탐색 및 Queen 놓기 μ‹œμž‘
	cout << answer;//7. μ •λ‹΅ 좜λ ₯

	return 0;
}

void N_Queen(int row) {
	if (row == N) {//2. ν˜„μž¬ νƒμƒ‰ν•˜λŠ” 행이 λ§ˆμ§€λ§‰ 행에 λ„λ‹¬ν–ˆλ‹€λ©΄ queen을 λͺ¨λ‘ λ°°μΉ˜ν–ˆλ‹€λŠ” λœ»μ΄λ―€λ‘œ answer + 1 ν•΄μ£ΌκΈ°
		answer++;
		return;//β˜…λ”μ΄μƒ νƒμƒ‰ν•˜μ§€ μ•Šκ³  리턴(bounding function)
	}
	for (int col = 0; col < N; ++col) {//3. queen을 놓을 수 μžˆλŠ”μ§€ μ—΄ 탐색
		queen_col[row] = col;//4. 넣을 수 μžˆλŠ” queen의 자리λ₯Ό μ €μž₯함
		if (isEmpty(row)) {//5. μ•„λž˜μ™€ λŒ€κ°μ„ μ΄ λΉ„μ–΄μžˆλŠ”μ§€ 탐색
			N_Queen(row + 1);//6. Queen 놓고 λ‹€μŒ ν–‰ νƒμƒ‰ν•˜λŸ¬ gogo
		}
	}
}

bool isEmpty(int row) {
	for (int col = 0; col < row; col++) {//5-1. 0ν–‰λΆ€ν„° ν˜„μž¬ ν–‰κΉŒμ§€ κ²ΉμΉ˜λŠ” Queen이 μžˆλŠ”μ§€ νƒμƒ‰ν•œλ‹€.
		if (queen_col[row] == queen_col[col] //5-2. 같은 열에 μžˆλŠ”μ§€ 탐색
			|| abs(queen_col[row] - queen_col[col]) == (row - col)) {//5-3. λŒ€κ°μ„ μ— μžˆλŠ”μ§€ 탐색
				return false;//β˜…Queen을 놓을 수 μ—†λ‹€λ©΄ 더이상 νƒμƒ‰ν•˜μ§€ μ•Šκ³  return(bounding function)
		}
	}
	return true;
}
728x90