티스토리 뷰

Algorithm/Solution

[백준 3055] - 탈출

기내식은수박바 2020. 3. 8. 18:58
반응형

 

문제

  • 사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다.
    • 이 숲에는 고슴도치가 한 마리 살고 있다.
    • 고슴도치는 제일 친한 친구인 비버의 굴로 가능한 빨리 도망가 홍수를 피하려고 한다.
  • 티떱숲의 지도는 R행 C열로 이루어져 있다.
    • 비어있는 곳은 '.'로 표시되어 있고, 물이 차있는 지역은 '*', 돌은 'X'로 표시되어 있다.
    • 비버의 굴은 'D'로, 고슴도치의 위치는 'S'로 나타내어져 있다.
  • 매 분마다 고슴도치는 현재 있는 칸과 인접한 네 칸 중 하나로 이동할 수 있다.
    • (위, 아래, 오른쪽, 왼쪽) 물도 매 분마다 비어있는 칸으로 확장한다.
    • 물이 있는 칸과 인접해있는 비어있는 칸(적어도 한 변을 공유)은 물이 차게 된다.
    • 물과 고슴도치는 돌을 통과할 수 없다.
    • 또, 고슴도치는 물로 차있는 구역으로 이동할 수 없고, 물도 비버의 소굴로 이동할 수 없다.
  • 티떱숲의 지도가 주어졌을 때, 고슴도치가 안전하게 비버의 굴로 이동하기 위해 필요한 최소 시간을 구하는 프로그램을 작성하시오.
  • 고슴도치는 물이 찰 예정인 칸으로 이동할 수 없다.
    • 즉, 다음 시간에 물이 찰 예정인 칸으로 고슴도치는 이동할 수 없다. 이동할 수 있으면 고슴도치가 물에 빠지기 때문이다. 

 

입력

  • 첫째 줄에 50보다 작거나 같은 자연수 R과 C가 주어진다.
    • 다음 R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다.

 

출력

  • 첫째 줄에 고슴도치가 비버의 굴로 이동할 수 있는 가장 빠른 시간을 출력한다.
    • 만약, 안전하게 비버의 굴로 이동할 수 없다면, "KAKTUS"를 출력한다.

 

 

솔루션

  • 고슴도치가 동굴까지 이동할 수 있는 최소 거리를 구하는 문제이다.
  • 고슴도치웅덩이를 시작점으로 하여 각각 BFS를 수행하면 된다.
    • 웅덩이가 다음번에 퍼지는 곳은 고슴도치가 이동할 수 없다는 조건이 있으므로, BFS웅덩이 다음 고슴도치 순서로 한다.
    • 웅덩이 ('*') 가 퍼질때마다 좌표 값을 확인한 뒤 돌멩이 ('X') 또는 동굴 ('D') 이 아니라면 (고슴도치 ('S') 또는 ('.')) 좌표 값을 웅덩이 ('*') 로 바꿔준다.
    • 고슴도치 ('S') 가 움직일때마다 좌표 값을 확인한 뒤 돌멩이 ('X')웅덩이 ('*') 가 아니라면 좌표 값을 고슴도치 ('S') 로 바꿔주고 이전 좌표 값은 ('.') 로 바꿔준다.
      • 만약 고슴도치가 이동한 곳이 동굴 ('D') 라면 현재까지 지난 시간 (minute) 를 반환하고 수행을 종료한다.
    • 웅덩이와 고슴도치가 모두 움직였다면, 현재 고슴도치가 동굴까지 갈 수 있는지 여부를 확인한다.
      • 동굴 사방이 돌 또는 웅덩이로 둘러싸여있는지
      • 현재 지도에서 고슴도치 ('S') 가 존재하는지
        • 두 가지 중 하나라도 해당이 된다면 동굴로 갈 수 있는 경우는 없으므로 수행을 종료한다.
    • 그 이외의 상황이라면 다시 처음부터 위 과정 (웅덩이와 고슴도치를 이동) 을 수행한다.
  • 그림을 통해 확인해보자. 

첫 번째 예시

  • 위 그림에서 1분씩 순서대로 진행하면 아래와 같을 것이다.

두 번째 예시

  • 두 번째 예시를 진행해보면 아래와 같을 것이다.
    • 결국 고슴도치는 동굴에 도달하지 못하게 된다.

  • 세 번째, 네 번째 예시도 마찬가지로 진행하되 돌멩이는 웅덩이, 고슴도치가 모두 지나갈 수 없다는 점을 유의해야 한다.

 

Code

1분당 고슴도치가 움직이고, 물이 퍼지는 과정을 진행하는 함수

1
2
3
4
5
6
7
8
9
10
11
12
public static String PerMinute() {
    minute++;
    SpreadPuddles();
    Move();
    
    if (cave == null)
        return Integer.toString(minute);
    else if (!isPossible() || hedgehog.size() == 0)
        return "KAKTUS";
    else
        return "";
}
cs

 

웅덩이가 퍼지도록 하는 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void SpreadPuddles() {
    Queue<Point> queue = new LinkedList<>();
 
    queue.addAll(puddles);
    puddles.clear();
 
    while (!queue.isEmpty()) {
        Point puddle = queue.poll();
 
        for (int i = 0; i < 4; i++) {
            int nx = dx[i] + puddle.x;
            int ny = dy[i] + puddle.y;
 
            if (0 <= nx && nx < N && 0 <= ny && ny < M) {
                if (map[nx][ny] == '.' || map[nx][ny] == 'S') {
                    map[nx][ny] = '*';
                    puddles.add(new Point(nx, ny));
                }
            }
        }
    }
}
cs

 

고슴도치가 움직이는 함수

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
public static void Move() {
    Queue<Point> queue = new LinkedList<>();
 
    queue.addAll(hedgehog);
    hedgehog.clear();
 
    while (!queue.isEmpty()) {
        Point h = queue.poll();
 
        if (map[h.x][h.y] == 'S')
            map[h.x][h.y] = '.';
 
        for (int i = 0; i < 4; i++) {
            int nx = dx[i] + h.x;
            int ny = dy[i] + h.y;
 
            if (0 <= nx && nx < N && 0 <= ny && ny < M) {
                if (map[nx][ny] == 'D') {
                    cave = null;
                    return;
                }
 
                if (!visited[nx][ny] && map[nx][ny] == '.') {
                    visited[nx][ny] = true;
                    map[nx][ny] = 'S';
                    hedgehog.add(new Point(nx, ny));
                }
            }
        }
    }
}
cs

 

동굴 주변을 확인하여 동서남북 모두 막혔는지 여부를 확인하는 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static boolean isPossible() {
    for (int i = 0; i < 4; i++) {
        int nx = dx[i] + cave.x;
        int ny = dy[i] + cave.y;
 
        if (0 <= nx && nx < N && 0 <= ny && ny < M) {
            if (map[nx][ny] == '*' || map[nx][ny] == 'X')
                continue;
 
            return true;
        }
    }
 
    return false;
}
cs

 

결과

 

 

 

 
반응형

'Algorithm > Solution' 카테고리의 다른 글

[프로그래머스] - 큰 수 만들기  (0) 2020.03.09
[백준 1261] - 알고스팟  (0) 2020.03.09
[백준 2146] - 다리 만들기  (0) 2020.03.07
[백준 1475] - 방 번호  (0) 2020.03.05
[백준 2504] - 괄호의 값  (2) 2020.03.04
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
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
글 보관함