본문 바로가기
Algorithm

백준 17836번 <공주님을 구해라!>

by seungh2 2023. 12. 14.

백준 알고리즘 17836번

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

 

17836번: 공주님을 구해라!

용사는 마왕이 숨겨놓은 공주님을 구하기 위해 (N, M) 크기의 성 입구 (1,1)으로 들어왔다. 마왕은 용사가 공주를 찾지 못하도록 성의 여러 군데 마법 벽을 세워놓았다. 용사는 현재의 가지고 있는

www.acmicpc.net


17836번

N x M 크기의 성이 있다. 성의 입구는 (1, 1)이며, 공주는 (N, M)에 갇혀있다. 이 성에는 여러 개의 마법 벽이 존재한다.

용사는 상하좌우로 이동하며 마왕이 가둬놓은 공주를 구하러 가는데, 공주가 저주에 걸려 T시간 안에 구해야 한다. 또한 용사는 그람(전설의 검)을 획득했을 때만 마법 벽을 부술 수 있다. (마법 벽을 부수는데 제한은 없다.)

성에는 그람 1개만 숨겨져 있고 그람을 획득하자마자 사용할 수 있다.

 

T시간 이내에 구출할 수 없으면 Fail을 출력하고 구출할 수 있다면 공주를 구하는데 걸리는 최소 시간을 출력하면 된다.


문제 해결

BFS를 사용해 문제를 해결했다.

 

문제를 읽어보면 그람 없이 공주를 구하거나, 그람 있이 공주를 구하거나, 공주를 못 구하는 경우 3가지가 있을 수 있다.

따라서 그람 없이 공주를 구하는데 걸리는 시간, 그람 있이 공주를 구하는데 걸리는 시간을 구하고, 이 2개의 시간 중 더 작은 시간을 가지고 공주를 구할 수 있는지 확인하면 된다.

 

work2goal(int[] goal) 함수를 만들어서 성의 입구에서 goal까지 가는데 걸리는 시간을 구했다.

work2goal(int[] goal)

  • BFS 알고리즘을 이용해서 성의 입구인 (0, 0)부터 goal까지 걸리는 시간을 구했다.
  • 먼저 성의 입구를 큐에 넣고, 방문 체크를 진행한다.
  • 큐에서 위치를 꺼내서 다음의 과정을 진행한다.
    • 큐에서 꺼낸 위치에서 상하좌우로 움직인다. 이때, 성을 벗어나거나 이미 방문한 위치거나, 벽이라서 못 가는 경우라면 가지 않는다.
    • 만약 새로운 위치가 goal이라면 그때의 시간에 1을 더해서 반환한다.
  • 큐에 아무것도 없다면 goal에 도착하지 못했다는 의미이기 때문에 큰 값(Integer.MAX_VALUE)를 반환한다.

그람 없이 공주를 구하는 시간은 work2goal( {N-1, M-1} ) 를 통해 구할 수 있다.

그람 있이 공주를 구하는 시간은 그람이 있는 곳까지 가는 시간과 그람이 있는 곳에서 (N-1, M-1)까지의 최단 시간을 더하면 된다. 따라서 work2goal( 그람이 있는 곳) + (N-1 - 그람의 위치 세로) (M-1 - 그람의 위치 가로) 로 구할 수 있다.

 

두 개의 값 중 공주를 못 구하는 경우를 거르고 최소 시간을 구하고 T 시간 이내인지 판단해 출력하면 된다.


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;

public class BOJ_17836 {
    static int N, M;
    static int[] di = {1, -1, 0, 0};
    static int[] dj = {0, 0, 1, -1};
    static int[][] board;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] inArr = br.readLine().split(" ");
        N = Integer.parseInt(inArr[0]);
        M = Integer.parseInt(inArr[1]);
        int T = Integer.parseInt(inArr[2]);
        int[] knife = new int[2];
        board = new int[N][M];
        for (int i = 0; i < N; i++) {
            inArr = br.readLine().split(" ");
            for (int j = 0; j < M; j++) {
                board[i][j] = Integer.parseInt(inArr[j]);
                if (board[i][j] == 2) knife = new int[]{i, j};
            }
        }
        // end input

        // 용사가 바로 공주가 있는 곳까지 가는 시간 (0, 0) -> (N-1, M-1)
        int direct = work2goal(new int[]{N - 1, M - 1});

        // 용사가 검이 있는 곳까지 가고 (0, 0) -> knife, 검을 들고 공주가 있는 곳까지 가는 시간 knife -> (N-1, M-1)
        int weapon = breakWall(work2goal(knife), knife);

        int answer = Math.min(direct, weapon);
        System.out.println(answer > T ? "Fail" : answer);
    }

    static int breakWall(int curr, int[] knife) {
        if (curr == Integer.MAX_VALUE) return Integer.MAX_VALUE;
        return curr + (N - 1 - knife[0]) + (M - 1 - knife[1]);
    }

    static int work2goal(int[] goal) {
        boolean[][] visit = new boolean[N][M];
        Queue<int[]> Q = new ArrayDeque<>();
        visit[0][0] = true;
        Q.add(new int[]{0, 0});
        int time = 0;
        while (!Q.isEmpty()) {
            int size = Q.size();
            for (int s = 0; s < size; s++) {
                int[] pnt = Q.poll();
                for (int k = 0; k < 4; k++) {
                    int ni = di[k] + pnt[0];
                    int nj = dj[k] + pnt[1];
                    if (ni < 0 || nj < 0 || ni >= N || nj >= M) continue;
                    if (visit[ni][nj] || board[ni][nj] == 1) continue;
                    if (ni == goal[0] && nj == goal[1]) return time + 1;
                    visit[ni][nj] = true;
                    Q.add(new int[]{ni, nj});
                }
            }
            time++;
        }
        return Integer.MAX_VALUE;
    }
}

결과


 

 

728x90

'Algorithm' 카테고리의 다른 글

백준 1253번 <좋다>  (0) 2024.01.05
백준 2589번 <보물섬>  (0) 2023.12.31
백준 2268번 <수들의 합7>  (0) 2023.12.06
백준 6087번 <레이저 통신>  (0) 2023.12.05
프로그래머스 <양과 늑대>  (0) 2023.12.01

댓글