KwanIk Devlog

1. 문제

 

1981번: 배열에서 이동

n×n짜리의 배열이 하나 있다. 이 배열의 (1, 1)에서 (n, n)까지 이동하려고 한다. 이동할 때는 상, 하, 좌, 우의 네 인접한 칸으로만 이동할 수 있다. 이와 같이 이동하다 보면, 배열에서 몇 개의 수를

www.acmicpc.net

 

2. 풀이

우선 (1, 1) 에서 (N, N)으로 가는 모든 경로를 탐색해야 하는 BFS 문제임은 맞지만, (최대 - 최소) 값이 최소가 되게 만들기 위해서 경로를 탐색하기 위해서는 특정한 기준이 필요하다. 여기서 기준이란 모든 경우를 만들어서 값을 만들어 볼 수는 없으니, 기준값을 만들어 해당 값으로 배열에서 (1, 1)부터 (N, N)까지의 경로가 있는지 확인하는 것이다. 그렇다면 이 기준을 어떻게 만들어 줄 것 인가에 초점을 맞춰야 한다.

 

이분탐색을 통한 기준점 마련

먼저 배열을 입력받을 때 우리는 최솟값과 최댓값을 미리 판단할 수가 있다. 이 두 값을 통해서 입력 받은 배열에서 (최대 - 최소)의 최댓값을 미리 산정할 수 있게 된다. 이를 통해 배열에서 만드는 경로는 '0 ~ (최댓값 - 최솟값)'의 범위의 응답값을 만들어 낼 수 있다는 것을 알 수 있다. 이 범위 내에서 이분탐색을 통해 mid 값을 만들고, BFS를 통해 mid 이하의 최종 응답값을 만들어내는 경로가 있는지 탐색한다. 이하 설명에서는 mid를 차이값으로 명명한다.

 

풀이 정리

  1. 배열 입력 시, 배열 요소의 최솟값과 최댓값 판단
    1. 초기 최댓값 = 배열 요소 최댓값 - 배열 요소 최솟값
  2. (0 ~ 초기 최댓값) 범위 내에서 이분탐색 실행
    1. 이분탐색의 기본 개념을 이용한 차이값 산출
    2. mid = (left + right) / 2 
  3. 이분탐색으로 만들어낸 mid(차이값)으로 탐색이 가능한지 BFS를 통해 확인
    1. 배열 최솟값 부터 최솟값에 차이값을 더한 범위 내에서 (N, N)까지 이동할 수 있는가를 확인

 

3. 소스코드

더보기
public class Main {
    static final int[] dy = {-1, 0, 1, 0};
    static final int[] dx = {0, 1, 0, -1};

    static int N, min = 201, max = -1;
    static int ans;
    static int[][] map;

    static void binary(int left, int right) {
        while (left <= right) {
            int mid = (left + right) / 2;

            if (bfs(mid)) {
                ans = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
    }

    static boolean bfs(int diff) {
        for (int flag = min; flag + diff <= max; flag++) {
            int start = flag;
            int end = flag + diff;

            if (map[0][0] < start || end < map[0][0]) continue;

            boolean[][] visit = new boolean[N][N];

            Queue<Integer> q = new LinkedList<>();
            q.add(0);
            visit[0][0] = true;

            while (!q.isEmpty()) {
                Integer now = q.poll();
                if (now / N == N - 1 && now % N == N - 1) {
                    return true;
                }

                for (int dir = 0; dir < 4; dir++) {
                    int ny = now / N + dy[dir];
                    int nx = now % N + dx[dir];

                    if (ny < 0 || nx < 0 || N <= ny || N <= nx || visit[ny][nx] || map[ny][nx] < start || end < map[ny][nx]) continue;

                    q.add(ny * N + nx);
                    visit[ny][nx] = true;
                }
            }
        }
        return false;
    }

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

        map = new int[N][N];
        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
                min = Math.min(min, map[i][j]);
                max = Math.max(max, map[i][j]);
            }
        }

        binary(0, max - min);

        bw.write(ans + "");
        bw.close();
        br.close();
    }
}

 

 

GitHub - kwanik-kor/BOJ: Baekjoon Online Judge - explanation of solved problems and complete code

Baekjoon Online Judge - explanation of solved problems and complete code - GitHub - kwanik-kor/BOJ: Baekjoon Online Judge - explanation of solved problems and complete code

github.com


BFS 개념은 아래 게시글 참고♥️

 

그래프와 BFS(Graph & Breadth First Search)

BFS(너비 우선 탐색) 알고리즘에 대해 알아보기 전에 필수적으로 알아봐야 할 자료구조는 바로 그래프(Graph)다. 그래프는 실질적으로 프로그래밍 언어 라이브러리 상에서 제공하기 보다는 추상적

kwanik.tistory.com

 

반응형

'Algorithm > 문제풀이' 카테고리의 다른 글

[ 백준 2573 ] 빙산  (0) 2023.02.13
[ 백준 16959 ] 체스판 여행 1  (0) 2023.02.09
[ 백준 26999 ] Satellite Photographs  (0) 2023.02.08
[ 백준 25416 ] 빠른 숫자 탐색  (0) 2023.02.07
[ 백준 2842 ] 집배원 한상덕  (0) 2020.07.27
profile

KwanIk Devlog

@갈닉

노력하는 개발자가 되고자 합니다. GitHub이나 블로그 모두 따끔한 피드백 부탁드립니다 :)