3 minute read



문제 풀이


이번 문제는 너비 우선 탐색인 BFS를 이용해 풀 수 있다.


아이디어 도출

보통, BFS를 이용하여 상,하,좌,우 4 방향으로 이동하는 문제가 많지만, 이번 문제에서는 이동할 수 있는 구간이 8 방향임을 고려하여 접근해야 한다.

나이트의 이동반경을 체스판 위에서 x,y 좌표로 살펴보자.

x 좌표 y 좌표
-2 -1
-2 1
-1 -2
1 2
1 -2
1 2
2 -1
2 1


위와 같이 8방향으로 BFS 탐색을 진행하면 된다. 이제 문제풀이를 위한 아이디어는 정리해보자.

  1. 각 테스트케이스마다 체스판의 변의 길이와 체스판 배열, 방문 배열을 초기화한다.
  2. 나이트의 시작위치와 목표위치를 입력받아 BFS 탐색을 진행하는데, 나이트의 시작위치를 먼저 큐에 삽입하여 탐색한다.
  3. BFS를 통해 나이트가 이동할 때마다(큐에 새로 삽입될 때마다) 이동횟수를 1씩 증가시킨다.
  4. BFS를 탐색하며 현재 나이트의 위치가 목표위치에 도달하게되면 탐색을 종료하고 여태까지의 이동횟수를 출력한다.


문제 풀이를 위해 작성한 코드는 아래와 같다.

작성코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import java.io.*;
import java.util.*;

class Main {    

    // 체스판의 크기 선언
    static int N;

    // 나이트 이동할 수 있는 8칸
    static int[] dx = new int[]{-2, -2, -1, -1, 1, 1, 2, 2};
    static int[] dy = new int[]{-1, 1, -2, 2, -2, 2, -1, 1};

    // 체스판 입력배열과 방문 배열 선언
    static int[][] arr;
    static boolean[][] visited;

    // 나이트의 시작위치와 종료위치를 담을 배열 선언
    static Node[] nodes;

    static int result;

    public static void main(String[] args) throws IOException {

        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
                
                // 1. 나이트는 총 8방향으로 움직일 수 있다.
                // 2. 나이트의 시작위치에서 BFS를 통해 탐색해가며 종료위치가 될 경우 탐색을 종료한다.
                // 3. 탐색 종료 후 이동횟수를 출력한다.

                int T = Integer.parseInt(br.readLine());
                while(T --> 0) {
                    N = Integer.parseInt(br.readLine());
                    arr = new int[N][N];
                    visited = new boolean[N][N];

                    // 나이트의 시작위치와 목표위치를 담는다.
                    nodes = new Node[2];
                    for(int i=0; i<2; i++) {
                        StringTokenizer st = new StringTokenizer(br.readLine());
                        int start = Integer.parseInt(st.nextToken());
                        int end = Integer.parseInt(st.nextToken());
                        nodes[i] = new Node(start, end);
                    }

                    // 나이트의 총 이동횟수를 담기 위한 초기화
                    result = 0;

                    // BFS 함수 호출하여 탐색을 시작한다.
                    bfs();
                    
                    bw.write(result+"\n");
                }
                
        }

    }

    public static void bfs() {
        // 큐에 시작위치를 담고, 방문 여부를 체크한다.
        Queue<Node> q = new LinkedList<>();
        q.offer(nodes[0]);
        visited[nodes[0].x][nodes[0].y] =true;
        
        // 이동해야할 목표 위치
        Node target = nodes[1];

        while(!q.isEmpty()) {
            Node now = q.poll();

            // 현재 위치가 종료 위치가 될 경우 탐색을 종료한다.
            if(now.x == target.x && now.y == target.y) {
                result = now.cnt;
                return;
            }

            for(int dir=0; dir<8; dir++) {
                int i = now.x + dx[dir];
                int j = now.y + dy[dir];
                
                if(!isRange(i, j)) {
                    continue;
                }

                if(!visited[i][j]) {
                    visited[i][j] = true;
                    q.offer(new Node(i, j, now.cnt+1));
                }
            }
        }
    }

    public static boolean isRange(int x, int y) {
        if(0<=x && 0<=y && x<N && y<N) {
            return true;
        }
        return false;
    }

}

/**
 * Node 클래스는 x,y 좌표와 이동횟수를 가진다.
 * x,y좌표만을 받아 Node의 인스턴스를 생성한다.
 * x,y좌표 및 cnt(이동횟수)를 받아 위치를 이동하는 Node의 인스턴스를 생성한다.
 */
class Node {
    
    int x;
    int y;
    int cnt;
    
    Node(int x, int y) {
        this.x = x;
        this.y = y;
        this.cnt = 0;
    }

    Node(int x, int y, int cnt) {
        this.x = x;
        this.y = y;
        this.cnt = cnt;
    }

}

출처


  • 해당 문제의 저작권은 문제를 만든이에게 있으며 자세한 내용은 문제 링크에서 참조바랍니다.