• Feed
  • Explore
  • Ranking
/
/
    λ§žμ•˜μŠ΅λ‹ˆλ‹€!!

    SWEA : 2806 N-Queen(JAVA)

    SWEA 2806 N-Queen 기둝 πŸ’‘
    μ•Œκ³ λ¦¬μ¦˜DFS
    t
    t1s
    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();
    
    	}
    
    }

    문제λ₯Ό ν’€λ©°

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

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







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