[백준 2589] 보물섬(Java)

최민길(Gale)·2023년 2월 11일
1

알고리즘

목록 보기
37/172

문제 링크 : https://www.acmicpc.net/problem/2589

이 문제는 bfs를 이용하여 풀 수 있습니다. 처음에 이 문제를 풀기 위해 첫 번째 보물의 위치와 두 번째 보물의 위치 모두 반복문으로 탐색해서 풀었는데 4중 for문 내에 bfs 코드가 동작하니 시간 초과가 나왔습니다. 따라서 이 문제는 조금 더 생각해서 풀어야 합니다.

가장 핵심적인 부분은 첫 번째 보물의 위치를 알면 두 번째 보물의 위치는 정해진다는 것입니다. 문제에서 두 보물은 최단 거리로 이동하는데 있어 가장 긴 시간이 걸리는 곳에 묻혀있습니다. 따라서 첫 번째 보물의 위치에서 가장 멀리 떨어진 위치가 바로 두 번째 보물이 묻혀 있는 위치입니다. 이 방식으로 반복문 수를 줄여 bfs로 결과를 출력하시면 되겠습니다.

다음은 코드입니다.

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

public class Main{
    static int N,M;
    static int res = 0;
    static boolean[][] req = new boolean[51][51];
    static boolean[][] check = new boolean[51][51];
    static int[] dy = {1,0,-1,0};
    static int[] dx = {0,1,0,-1};

    static void bfs(int i, int j){
        check[i][j] = true;
        Queue<Treasure> queue = new LinkedList<>();
        queue.add(new Treasure(i,j,0));

        // 첫 번째 보물 위치만 움직여서 결과 출력
        while(!queue.isEmpty()){
            Treasure curr = queue.poll();
            int y = curr.y;
            int x = curr.x;
            int cnt = curr.cnt;

            // 만약 첫 번째 보물이 두 번째 보물 위치까지 도달했다면 max와 최댓값 비교
            if(res < cnt) res = cnt;

            // 첫 번째 보물 위치 이동
            for(int dir=0;dir<4;dir++){
                int ny = y + dy[dir];
                int nx = x + dx[dir];
                if(ny<0 || ny>=N || nx<0 || nx>=M) continue;

                // 지나간 경로가 아니고 현재 위치가 땅이라면 큐에 cnt 증가시켜 저장
                if(!check[ny][nx] && req[ny][nx]){
                    check[ny][nx] = true;
                    queue.add(new Treasure(ny,nx,cnt+1));
                }
            }
        }
    }

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        for(int i=0;i<N;i++){
            st = new StringTokenizer(br.readLine());
            String str = st.nextToken();
            for(int j=0;j<M;j++){
                req[i][j] = str.charAt(j) != 'W';
            }
        }

        // 첫 번째 보물 위치에 대응하는 두 번째 보물 위치는 정해져 있음
        // 따라서 첫 번째 보물만 bfs로 탐색
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                check = new boolean[51][51];
                if(req[i][j]){
                    bfs(i,j);
                }
            }
        }
        System.out.println(res);
    }
}

class Treasure{
    int y;
    int x;
    int cnt;

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

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보