자료구조/문제풀이

[백준 JAVA] 7562 나이트의 이동

휴먼코딩 2024. 8. 24. 09:34

7562 나이트의 이동

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

문제설명

체스판의 크기와 여러 테스트 케이스에 대해 나이트가 시작점에서

목표점까지 이동하는 데 필요한 최소 이동 횟수를 계산한다.

접근방식

O(I^2)  시간복잡도

 

나이트는 최대 8방향으로 이동할 수 있다. 각 정점에서 최대 8개의 간선을 탐색할때 O(E) 의 BFS가 소요된다.

체스판의 크기가 I x I이므로 전체 정점의 수는 O(I^2)의 시간이 소요된다.

 

문제 조건 분석 과정

  • 체스판: 크기가 I x I인 체스판이다.
  • 나이트의 이동: 나이트는 8가지 방향으로 이동할 수 있다.
  • 시작점을 큐에 추가하고, 방문 여부를 기록한다.
  • 큐에서 위치를 꺼내며, 나이트의 모든 이동 가능 위치를 탐색한다.
  • 각 이동에 대해 체스판의 경계와 방문 여부를 확인한다.
  • 이동 횟수를 업데이트하고 목표점에 도달할 때까지 반복한다.

전체코드

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

public class Main {
    static int I; // 체스판의 크기 (I x I)
    static int x1, x2, y1, y2; // 시작점과 목표점의 좌표
    static int[][] arr; // 각 위치까지의 이동 횟수를 저장할 배열
    static boolean[][] visited; // 방문 여부를 저장할 배열
    static int[] dx = {1, 2, 2, 1, -1, -2, -2, -1}; // 나이트의 이동을 위한 x 방향
    static int[] dy = {2, 1, -1, -2, -2, -1, 1, 2}; // 나이트의 이동을 위한 y 방향

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        int T = Integer.parseInt(br.readLine()); // 테스트 케이스 수 읽기

        for (int i = 1; i <= T; i++) {
            I = Integer.parseInt(br.readLine()); // 체스판의 크기 입력

            arr = new int[I][I]; // 각 위치까지의 이동 횟수를 저장할 배열 초기화
            visited = new boolean[I][I]; // 방문 여부를 저장할 배열 초기화

            st = new StringTokenizer(br.readLine());
            x1 = Integer.parseInt(st.nextToken()); // 시작점의 x 좌표
            y1 = Integer.parseInt(st.nextToken()); // 시작점의 y 좌표
            st = new StringTokenizer(br.readLine());
            x2 = Integer.parseInt(st.nextToken()); // 목표점의 x 좌표
            y2 = Integer.parseInt(st.nextToken()); // 목표점의 y 좌표

            bfs(); // 너비 우선 탐색 수행

            sb.append(arr[x2][y2]).append("\n");
        }
        System.out.println(sb); // 모든 테스트 케이스 결과를 출력
    }

    public static void bfs() {
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{x1, y1}); // 시작점을 큐에 추가
        visited[x1][y1] = true; // 시작점을 방문 처리

        while (!q.isEmpty()) {
            int[] now = q.poll(); // 큐에서 현재 위치를 꺼냄
            int nx = now[0];
            int ny = now[1];

            for (int i = 0; i < 8; i++) {
                int ox = nx + dx[i]; // 새로운 x 좌표 계산
                int oy = ny + dy[i]; // 새로운 y 좌표 계산

                // 새로운 좌표가 체스판 내에 있는지 확인
                if (ox >= 0 && oy >= 0 && ox < I && oy < I) {
                    if (!visited[ox][oy]) { // 해당 위치가 방문되지 않았으면
                        q.add(new int[]{ox, oy}); // 큐에 새로운 위치 추가
                        arr[ox][oy] = arr[nx][ny] + 1; // 이동 횟수 업데이트
                        visited[ox][oy] = true; // 새로운 위치 방문 처리
                    }
                }
            }
        }
    }
}