코딩테스트

[백준-7562번 자바/java] 나이트의 이동 _디버깅의 눈물

디버깅의 눈물 2022. 9. 14. 10:59

https://www.acmicpc.net/problem/7562

 

7562번: 나이트의 이동

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수

www.acmicpc.net

 

 

 

 

나이트의 이동 성공다국어

한국어   
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 256 MB 41290 20808 15578 49.402%

문제

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수 있을까?

입력

입력의 첫째 줄에는 테스트 케이스의 개수가 주어진다.

각 테스트 케이스는 세 줄로 이루어져 있다. 첫째 줄에는 체스판의 한 변의 길이 l(4 ≤ l ≤ 300)이 주어진다. 체스판의 크기는 l × l이다. 체스판의 각 칸은 두 수의 쌍 {0, ..., l-1} × {0, ..., l-1}로 나타낼 수 있다. 둘째 줄과 셋째 줄에는 나이트가 현재 있는 칸, 나이트가 이동하려고 하는 칸이 주어진다.

출력

각 테스트 케이스마다 나이트가 최소 몇 번만에 이동할 수 있는지 출력한다.

예제 입력 1 복사

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

예제 출력 1 복사

5
28
0

 

 

 

 


 

 

 

체크 포인트

 

1. 너비 우선 탐색(BFS) 문제

-나이트가 목표지점까지 '최소 몇번의 이동'으로 움직일 수 있는지를 찾는 문제

 

 

2. 나이트의 이동방향 설정

 

	// 나이트 이동 방향
	static int[] dx = {-2,-2,-1,-1,1,1,2,2};
	static int[] dy = {-1,1,-2,2,-2,2,-1,1};

 

 

3. 나이트의 현재 칸/나이트의 이동목표 칸의 구분

 

-기준점 = 나이트의 현재 위치

-목표점 = 나이트가 최종 이동해야할 위치

	    		// 기준점
	    		if(i==0){
	    			map[a][b] = 1;
	    			// 기준점을 큐에 넣어준다.
	    			Q.add(new Integer[]{a,b});
	    		}
	    		// 목표점
	    		else{
	    			map[a][b] = -1;
	    		}

 

 

4. 나이트의 이동거리 계산

 

    				// 방문했던 적이 없는 곳이면,
    				if(map[nx][ny]==0){
    					// 방문 처리(이동수 +1 처리)
    					map[nx][ny] = map[x][y] + 1;
    					// (nx,ny)에서 BFS 탐색 시작을 위한 추가
    					Q.add(new Integer[]{nx,ny});
    				}

 

-새로운 map[nx][ny]의 값을 이전 map[n][y]의 값에 + 1로 처리하여, 이전보다 한칸 더 이동했음을 표시

 

 

풀이

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public  class Main {
	// 테스트 케이스의 가지수 T, 체스판 한변의 길이 I
	static int T,I;
	// 체스판 배열
	static int[][] map;
	
	// 나이트 이동 방향
	static int[] dx = {-2,-2,-1,-1,1,1,2,2};
	static int[] dy = {-1,1,-2,2,-2,2,-1,1};
	
	static Queue<Integer[]> Q;
	 
    public static void main(String[] args) throws IOException {
    	
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	
    	StringTokenizer st = new StringTokenizer(br.readLine());
    	
    	// 테스트 케이스
    	T = Integer.parseInt(st.nextToken());
    	
    	for(int k=0; k<T; k++){

        	st = new StringTokenizer(br.readLine());
        	// 체스판 한변의 길이
        	I = Integer.parseInt(st.nextToken());
        	
        	// 배열 초기화
	    	map = new int[I][I];
	    	// 큐 초기화
	    	Q = new LinkedList<Integer[]>();
	    	
	    	// 두 점의 위치 정보 입력
	    	for(int i=0; i<2; i++){
	    		st = new StringTokenizer(br.readLine(), " ");
	    		
	    		int a = Integer.parseInt(st.nextToken());
	    		int b = Integer.parseInt(st.nextToken());
	    		
	    		
	    		// 기준점
	    		if(i==0){
	    			map[a][b] = 1;
	    			// 기준점을 큐에 넣어준다.
	    			Q.add(new Integer[]{a,b});
	    		}
	    		// 목표점
	    		else{
	    			map[a][b] = -1;
	    		}
	    	}
	    	// BFS 탐색 시작
	    	BFS();

    	}
    }
    
    static void BFS() {
    	
    	while(!Q.isEmpty()){
    		Integer[] temp = Q.poll();
    		
    		int x = temp[0];
    		int y = temp[1];
    		
    		// 나이트의 이동 구간 탐색
    		for(int i=0; i<8; i++){
    			int nx = x + dx[i];
    			int ny = y + dy[i];
    			
    			// 체스판 위에 존재하고,
    			if(nx>=0 && ny>=0 && nx<I && ny<I){
    				// 방문했던 적이 없는 곳이면,
    				if(map[nx][ny]==0){
    					// 방문 처리(이동수 +1 처리)
    					map[nx][ny] = map[x][y] + 1;
    					// (nx,ny)에서 BFS 탐색 시작을 위한 추가
    					Q.add(new Integer[]{nx,ny});
    				}
    				// 목표점에 도달했다면,
    				else if(map[nx][ny]==-1){
    					// 결과 출력
    					System.out.println(map[x][y]);
    					return;
    				}
    				
    			}
    		}
    		
    		
    	}
    	
    	
    } // end of BFS
    

} // end of Main