SWEA : 2806 N-Queen(JAVA)

SWEA 2806 N-Queen 기둝 πŸ’‘
μ•Œκ³ λ¦¬μ¦˜DFS
avatar
2025.05.09
Β·
9 min read

문제

문제
μ‹œκ°„ μ œν•œ 4초, νž™+정적 256MB 이내 ν˜Ήμ€ μŠ€νƒ 256MB 이내

퀸은 같은 ν–‰, μ—΄, λ˜λŠ” λŒ€κ°μ„  μœ„μ— μžˆλŠ” 말을 곡격할 수 μžˆλ‹€.
N*N λ³΄λ“œμ— N개의 퀸을 μ„œλ‘œ λ‹€λ₯Έ 두 퀸이 κ³΅κ²©ν•˜μ§€ λͺ»ν•˜κ²Œ λ†“λŠ” 경우의 μˆ˜λŠ” λͺ‡κ°€μ§€κ°€ μžˆμ„κΉŒ?
N이 μ£Όμ–΄μ‘Œμ„ λ•Œ, 퀸을 λ†“λŠ” λ°©λ²•μ˜ 수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯
ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 수 T
λ³΄λ“œμ˜ κ°€λ‘œμ™€ μ„Έλ‘œ κ°’, ν€Έμ˜ 개수 (1 ≀ N ≀ 10)

좜λ ₯
퀸을 λ†“λŠ” λ°©λ²•μ˜ 수

풀이

문제λ₯Ό 읽은 ν›„μ˜ 생각듀을 μ­‰ λ‚˜μ—΄ν•΄λ³΄λ©΄...
일단 N도 10 이내고 μ‹œκ°„ μ œν•œλ„ 4초라, μ™„μ „νƒμƒ‰μœΌλ‘œ ν’€μ–΄λ³Ό λ§Œν•˜λ‹€λŠ” 생각을 ν–ˆλ‹€.
μž¬κ·€λ₯Ό μ‚¬μš©ν•˜μ—¬ ν’€λ˜, μœ„μ—μ„œ λ‚΄λ €μ˜€λ©° 퀸을 λ†“λŠ”λ‹€.
퀸을 놓을 수 μžˆλŠ”μ§€ 확인할 λ•Œ μœ„ μ„Έλ‘œ, μœ„ λŒ€κ°μ„ μ„ νŒŒμ•…ν•˜κ³  ν•΄λ‹Ή μœ„μΉ˜ 쀑에 퀸이 μžˆλŠ” 경우 더 μž¬κ·€λ¬Έμ„ λŒλ¦¬μ§€ μ•ŠλŠ”λ‹€.

κ°„λ‹¨ν•˜κ²Œ 2둜 μ˜ˆμ‹œλ₯Ό λ“€μ–΄ 생각해보면...
0,0에 λ„£λŠ” 경우 row++ν•˜κ³  1,0κ³Ό 1,1에 λ„£λŠ” 경우λ₯Ό check ν•¨μˆ˜λ‘œ ν™•μΈν•œλ‹€.
0,1에 λ„£λŠ” 경우 row++ν•˜κ³  1,0κ³Ό 1,1에 λ„£λŠ” 경우λ₯Ό check ν•¨μˆ˜λ‘œ ν™•μΈν•œλ‹€.
λ‘˜ λ‹€ 더 λ‚΄λ €κ°ˆ rowκ°€ μ—†μŒ -> 0 λ°˜ν™˜, λͺ¨λ“  경우의 μˆ˜κ°€ 0을 λ°˜ν™˜ => 값은 0

4둜 μ˜ˆμ‹œλ₯Ό λ“€λ©΄...
0,0에 λ„£λŠ” 경우 row++ ν•˜κ³ 
1,0에 λ„£λŠ”λ‹€ β†’ μ•ˆ 됨(μ§„ν–‰X)
1,1에 λ„£λŠ”λ‹€ β†’ μ•ˆ 됨(μ§„ν–‰X)
1,2에 λ„£λŠ”λ‹€ β†’ κ°€λŠ₯ν•˜λ―€λ‘œ μ§„ν–‰, 2,0 2,1 2,2 2,3에 넣어보며 λ˜λŠ”μ§€ μ§„ν–‰
1,3에 λ„£λŠ”λ‹€ β†’ κ°€λŠ₯ν•˜λ―€λ‘œ μ§„ν–‰, 2,0 2,1 2,2 2,3에 넣어보며 λ˜λŠ”μ§€ μ§„ν–‰

이 생각을 기반으둜 μž‘μ„±ν•΄λ³Έ 첫 μ½”λ“œλŠ” μ΄λŸ¬ν–ˆλ‹€. (🚧 잘λͺ»λœ μ½”λ“œ 🚧)

public class Solution {
	static int N;
	static int[][] drc = {
			{-1, 0},
			{-1, -1}, {-1, 1}
	};
	
	static int dfs(boolean[][] board, int row, int col) {
		int result = 0;
		
		if(!check(board, row, col)) { // λΆˆκ°€λŠ₯ν•œ 경우 μΆ”κ°€ 탐색 X
			return 0;
		}
		
		if(row == N-1) { // checkλŠ” 이미 μƒλ‹¨μ—μ„œ 톡과, row == N이면 끝, return 1;
			return 1;
		}
		
		for(int i=row; i<N-1; i++) {
			for(int j=col; j<N; j++) {
				board[i][j] = true;
				for(int k=0; k<N; k++) {
					result += dfs(board, i+1, k);
				}
				board[i][j] = false;
			}
		}
		
		return result;
	}
	
	static boolean check(boolean[][] board, int row, int col) {
		for(int i=0; i<3; i++) { // drcλ₯Ό μˆœνšŒν•˜λ©΄μ„œ λ”ν•˜κ³  λΉΌκ³  ν•  κ±°μž„
			int nR = row + drc[i][0];
			int nC = col + drc[i][1];
			
			// r, c에 drc 3개λ₯Ό 각각 λ”ν•˜λ©° 0μ΄λ‚˜ N을 λ„˜μ§€ μ•Šμ„ λ•ŒκΉŒμ§€ 확인
			while(nR >= 0 && nR < N
					&& nC >= 0 && nC < N) {
				
				if(board[nR][nC]) {
					return false;
				}
				
				nR += drc[i][0];
				nC += drc[i][1];
			}
		}
		return true;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		// N*N λ³΄λ“œμ— N개의 퀸을 κ³΅κ²©ν•˜μ§€ λͺ» ν•˜κ²Œ λ†“λŠ” 경우
		int T = Integer.parseInt(br.readLine());
		
		for(int tc=1; tc<=T; tc++) {
			// 확인할 λ•Œ : μœ„λ§Œ λ³Έλ‹€ (μ•„λž˜λŠ” κ³ λ € X)
			// μœ„μ—μ„œλΆ€ν„° λ‚΄λ €μ˜€λ©΄μ„œ 놓을 κ±°λ‹ˆκΉŒ
			N = Integer.parseInt(br.readLine());
			
			boolean[][] board = new boolean[N][N];
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
					board[i][j] = false;
				}
			}
			
			int result = 0;
			// checkν•˜κ³  trueλ°›λŠ” κ²½μš°μ—λ§Œ λ‹€μŒ col둜 λ„˜κΈ΄λ‹€
			bw.write("#" + tc + " " + dfs(board, 0, 0) + "\n");	
		}
		bw.flush();
		bw.close();
		br.close();
	}
}

1κ³Ό 2κΉŒμ§€λŠ” 잘 μž‘λ™ν–ˆμ§€λ§Œ 4의 값이 40이 λ‚˜μ™”λ‹€.
μ½˜μ†”μ°½μ— 값을 μ°μ–΄λ³΄λ‹ˆκΉŒ λ§€ 열에 μ΅œμ†Œ 1κ°œλŠ” μžˆμ–΄μ•Ό Nκ°œκ°€ λ˜λŠ”λ°, μ–΄λ””μ„ κ°€ false둜 λ³€ν•œ 배열도 λ“€μ–΄μ™€μ„œ 같이 checkλ₯Ό 돌고 같이 좜λ ₯λ˜λŠ” λͺ¨μ–‘μ΄μ—ˆλ‹€.

μˆ˜μ •μ„ 계속 ν•˜λ˜ 와쀑... rowλ₯Ό ꡳ이 for문으둜 돌 ν•„μš”κ°€ μ—†λ‹€λŠ” κ±Έ κΉ¨λ‹¬μ•˜λ‹€.
λ‚΄ μƒκ°μ—λŠ” 0~NκΉŒμ§€ rowλ₯Ό λŒμ•„μ•Ό ν•œλ‹€κ³  μƒκ°ν•΄μ„œ μ €λ ‡κ²Œ μž‘μ„±ν–ˆμ—ˆλŠ”λ°, 각 ν–‰μ—λŠ” 퀸을 ν•˜λ‚˜λ§Œ 두면 λ˜λ―€λ‘œ rowκΉŒμ§€ for문을 돌릴 ν•„μš” 없이 col만 for문을 돌리면 됐닀.

rowλŠ” μž¬κ·€ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λ‘œ λ³΄λ‚΄μ„œ 1μ”© 늘릴 κ²ƒμ΄λ‹ˆ for문을 μ œκ±°ν•œλ‹€.
col을 0~NκΉŒμ§€ μˆœνšŒν•˜λ©° 놓기 μ „, check ν•¨μˆ˜λ‘œ 놓을 수 μžˆλŠ” μœ„μΉ˜μΈμ§€ ν™•μΈν•œλ‹€. 퀸을 놓을 수 μžˆλŠ” 경우, board[row][col] = true;둜 λ³€κ²½ν•΄ 퀸을 λ†“μ•˜λ‹€κ³  λ°°μ—΄μ˜ 값을 λ³€κ²½ν•΄μ£Όκ³ , μž¬κ·€λ¬Έμ„ λŒλ¦°λ‹€.
이후 λ‹€μŒ col 값을 돌기 μ „ false;둜 λ°°μ—΄μ˜ 값을 λ³€κ²½ν•΄μ€€λ‹€.

import java.io.*;
import java.util.*;

public class Solution {
	static int N;
	static int[][] drc = {
			{-1, 0},
			{-1, -1}, {-1, 1}
	};
	
	static int dfs(boolean[][] board, int row) {
		int result = 0;
		
		if(row == N) { // checkλŠ” 이미 μƒλ‹¨μ—μ„œ 톡과, row == N이면 끝, return 1;
			return 1;
		}
		
		for(int col=0; col<N; col++) {
			if(check(board, row, col)) {
				board[row][col] = true;
				result += dfs(board, row+1);
				board[row][col] = false;
			}
		}
		
		return result;
	}
	
	static boolean check(boolean[][] board, int row, int col) {
		for(int i=0; i<3; i++) { // drcλ₯Ό μˆœνšŒν•˜λ©΄μ„œ λ”ν•˜κ³  λΉΌκ³  ν•  κ±°μž„
			int nR = row + drc[i][0];
			int nC = col + drc[i][1];
			
			// r, c에 drc 3개λ₯Ό 각각 더 ν•˜λ©° 0μ΄λ‚˜ N을 λ„˜μ§€ μ•Šμ„ λ•ŒκΉŒμ§€ 확인
			while(nR >= 0 && nR < N
					&& nC >= 0 && nC < N) {
				
				if(board[nR][nC]) {
					return false;
				}
				
				nR += drc[i][0];
				nC += drc[i][1];
			}
		}
		return true;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		// N*N λ³΄λ“œμ— N개의 퀸을 κ³΅κ²©ν•˜μ§€ λͺ» ν•˜κ²Œ λ†“λŠ” 경우
		
		int T = Integer.parseInt(br.readLine());
		
		for(int tc=1; tc<=T; tc++) {
			N = Integer.parseInt(br.readLine());
			
			boolean[][] board = new boolean[N][N];
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
					board[i][j] = false;
				}
			}
			
			bw.write("#" + tc + " " + dfs(board, 0) + "\n");	
		}

		bw.flush();
		bw.close();
		br.close();

	}

}

문제λ₯Ό ν’€λ©°

ν•œ 번 생각을 잘λͺ»ν•΄μ„œ μ‚½μ§ˆν•˜κΈ° μ‹œμž‘ν•˜λ©΄ 정말 μ‹œκ°„μ„ 끝도 없이 μž‘μ•„λ¨ΉλŠ” 것 κ°™λ‹€. 이럴 땐 κ·Έλƒ₯ λ‹€λ₯Έ 문제 ν’€λ‹€κ°€ λŒμ•„μ™€μ„œ μ½”λ“œ μ „λΆ€ 주석 μ²˜λ¦¬ν•˜κ³  μ²˜μŒλΆ€ν„° λ‹€μ‹œ 생각해봐야 ν•˜λ‚˜ 고민이 λœλ‹€. μ§€κΈˆμ΄μ•Ό μ—°μŠ΅ μ‚Όμ•„ ν‘ΈλŠ” κ±°λ‹ˆ 잠깐 걸으며 머릿속을 μ •λ¦¬ν•˜λŠ” μ‹œκ°„μ„ κ°€μ§ˆ 수 μžˆμ§€λ§Œ, μ½”λ”© ν…ŒμŠ€νŠΈλ₯Ό λ³Ό λ•ŒλŠ” 그럴 수 μ—†μœΌλ‹ˆκΉŒ... πŸ₯Ί

흠... μ²˜μŒλΆ€ν„° μ½”λ“œλ₯Ό 꼬이지 μ•Šκ²Œ μ§€ 수 μžˆκ²Œλ” μ΅œλŒ€ν•œ μ—°μŠ΅μ„ 많이 ν•΄λ³΄λŠ” 수 밖에 μ—†κ² λ‹€!







- μ»¬λ ‰μ…˜ 아티클