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

 

3055번: 탈출

문제 사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제일 친한 친구인 비버의 굴로 가능한 빨리 도망가 홍수를 피하려고 한다. 티떱숲의 지도는 R행 C열로 이루어져 있다. 비어있는 곳은 '.'로 표시되어 있고, 물이 차있는 지역은 '*', 돌은 'X'로 표시되어 있다. 비버의 굴은 'D'로, 고슴도치의 위치는 'S'로 나

www.acmicpc.net

이 문제는 물의 이동시간고슴도치의 이동시간을 비교해주어야 하기 때문에 둘 다 구해준다.

먼저 물이 차는 시간을 구해 놓고 고슴도치를 이동시키는 것이 편하다.

 

먼저 비버굴의 위치와 고슴도치의 위치를 따로 저장해놓고 물일 때는 바로 큐에 넣어준다.

bfs로 물이 차는 시간을 모두 구했으면 고슴도치의 위치를 시작으로 다시 bfs를 시작한다.

 

고슴도치의 경우 다음과 같이 물이 차는 시간과 비교해주는 부분이 중요하다!

 

처음에

 if(w[nx][ny] == s[x][y]+1continue;

이렇게 해줬다가 예제는 다 맞는데 틀려서 고민하다가 이미 더 빠른 시간에 차있는 경우가 생각나서

 

 if(w[nx][ny] <= s[x][y]+1continue;

이렇게 고쳤는데 예제마저 다 틀려버려서 당황했었다.

 

w배열을 방문 확인을 같이 하기 위해 -1로 초기화한 것을 까먹었다ㅠㅠ

최종적으로

 if(w[nx][ny] != -1 && w[nx][ny] <= s[x][y]+1continue;

이렇게 해주면 완벽하다!

 

마지막으로 비버 굴이 초기값이 아니면(도착시간이 저장되어 있으면) 도착시간을 출력해주고

초기값(-1)이면 KACTUS를 출력해준다.


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
 
int main() {
    int r,c;
    scanf("%d %d"&r, &c);
 
    char map[50][50];
    int s[50][50];
    int w[50][50];
 
    int dx[] = {0,0,1,-1};
    int dy[] = {1,-1,0,0};
 
 
    //이동 시간을 저장해줄 배열을 -1로 초기화
    memset(s,-1,sizeof(s));
    memset(w,-1,sizeof(w));
 
    int dochiX, dochiY;
    int beaverX, beaverY;
 
    queue<pair<int,int> > q;
 
 
    //input
    for(int i=0; i<r; i++) {
      
        for(int j=0; j<c; j++) {
            cin >> map[i][j];
 
            //비버굴 위치
            if(map[i][j] == 'D') {
                beaverX = i;
                beaverY = j;
            } else if(map[i][j] == 'S') {
                //고슴도치 위치
                dochiX = i;
                dochiY = j;
            } else if(map[i][j] == '*') {
                //물인 경우
                q.push(make_pair(i,j));
                w[i][j] = 0;
            }
        }
    }
 
    //물 차는 시간 먼저 계산
    while(!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for(int i=0; i<4; i++) {
            int nx = x+dx[i];
            int ny = y+dy[i];
            
            //범위 체크
            if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue;
            //돌이거나 비버굴인 경우 이동 불가
            if(map[nx][ny] == 'X' || map[nx][ny] == 'D'continue;
            //방문하지 않은 칸이면 방문
            if(w[nx][ny] == -1) {
                q.push(make_pair(nx,ny));
                w[nx][ny] = w[x][y] + 1;
            }
        }
    }
 
    //고슴도치 이동
    q.push(make_pair(dochiX,dochiY));
    s[dochiX][dochiY] = 0;
    while(!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for(int i=0; i<4; i++) {
            int nx = x+dx[i];
            int ny = y+dy[i];
 
            //범위 체크
            if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue;
 
            //돌인경우 이동 불가
            if(map[nx][ny] == 'X'continue;
 
            //이동하는 곳에 물이 차는 시간이 고슴도치가 이동하는 시간보다 적은 경우
            //초기값을 위에서 -1 로 해줬으므로 주의 해야한다!!
            if(w[nx][ny] != -1 && w[nx][ny] <= s[x][y]+1continue;
 
            //방문하지 않은 경우
            if(s[nx][ny] == -1) {
                q.push(make_pair(nx,ny));
                s[nx][ny] = s[x][y] + 1;
            }
 
        }
    }
 
 
    //비버굴에 도착하지 못하는 경우
    if(s[beaverX][beaverY] == -1) {
        cout << "KAKTUS";
    } else { //도착한 경우 도착한 시간을 출력
        cout << s[beaverX][beaverY];
    }
 
    return 0;
}
Colored by Color Scripter
 
 

'BOJ' 카테고리의 다른 글

[BOJ] 14442. 벽 부수고 이동하기 2  (0) 2019.06.28
[BOJ] 2206. 벽 부수고 이동하기  (0) 2019.06.28
[BOJ] 14501. 퇴사  (0) 2019.06.27
[BOJ] 1697. 숨바꼭질  (0) 2019.06.27
[BOJ] 7569. 토마토 (3차원)  (0) 2019.06.27

+ Recent posts