백준의 화산쇄설류(16569) 문제이다.

[ 문제 바로가기 ]


[ 문제풀이 ]

1) 문제에서 구현해야 할 것이 몇가지 있기 때문에 어떻게 접근해야 하는지 부터 차근차근 알아가보도록 하자.

   문제를 간략하게 요약하면 이렇다. "화산이 곧 폭팔하는데, 폭팔하면 화산 쇄설류들이 주변 산들로 퍼져나간다.

   그런데 재상이는 화산 & 화산 쇄설류가 있는 곳으로는 갈 수가 없다. 이 때, 재상이가 갈 수 있는 가장 높은 곳은

   높이가 얼마이고 그 까지 가는데 몇 초가 걸리냐?" 이다.


   본인은 먼저 화산에 대한 계산을 모두 끝낸 후에 재상이를 움직여 주었다. 또한, 재상이가 움직일 때 화산의 상태를

   계속해서 비교해야 하기 때문에 화산에 대한 계산을 모두 진행하고, 그 결과값을 또 다른 2차원 맵을 하나 만들어서

   저장해 놓았다.

   여기서 말하는 결과값은 무엇일까?? 바로 화산이 퍼지는 시간이다. 쉽게 말하면 다음과 같은 맵을 만들었다는 것이다.

  

   위의 그림에 대해서 간략하게 설명해보자면, 현재 0초이고 가운데 빨강색으로 표시된 화산은 0초에서 폭팔한다.

   그리고 위의 검은색으로 표시된 화산은 10초에 폭팔한다고 가정해보면,

   왼쪽 맵의 상태를 오른쪽 맵으로 표현한 것이다. 오른쪽 맵에서 숫자는 화산 쇄설류가 흐르는 시간을 의미한다.

   이렇게, 화산쇄설류들이 퍼지는 시간을 따로 만들어서 저장해 주었다.

  

   위와 같이 화산에 대한 맵을 만들었다면, 이제 재상이를 움직여 주면 된다. 재상이가 움직일 때 신경써야할 것은 딱 2가지

   이다.

   1. 움직이려는 좌표가 화산인지 아닌지

   2. 움직이려는 좌표가 화산이 아니라면, 재상이가 움직이는 시간과 기존에 화산맵에 저장해둔 시간을 비교해서

     재상이가 움직일 수 있는 좌표인지 이렇게 2가지만 비교해주면 된다.


2) 그렇다면 구현에 대한 이야기로 넘어가겠다. 먼저 화산맵을 만들어보자.

   위에서 설명하지 않았지만, 정확하게 본인은 기존에 입력받는 맵 이외에 2개의 맵을 더 만들어 주었다.

   하나는 화산인지 아닌지를 체크해주는 맵(본문 : Volcano_MAP[][]),

   또 하나는 화산 쇄설류가 흐르는 시간을 저장해주는 맵(본문 : Volcano_Time[][])

   화산인지 아닌지를 체크해주는 맵은 정말 간단하다. 화산인 지점만 -1로 표현되어 있고 나머지 부분은 모두 0으로 표시되어

   있는 맵이다. 굳이 이렇게 맵을 2개를 만든 이유는 아래에서 설명하겠다.

   중요한건, 화산인지 아닌지를 체크해주는 Volcano_MAP이 아닌, Volcano_Time이다. 본인은 이 부분을 구현하기 위해서

   BFS탐색기법을 이용해서 시간을 비교하면서 구현해 주었다.

   이렇게 화산의 시간에 대한 맵을 모두 만들었다면 재상이를 움직여주면 된다. 재상이가 움직일 조건은 위에서 말했던

   2가지이다.

   그런데 위에서 말했던 2번 조건을 한번 봐보도록 하자. 기존의 화산시간맵에 저장해둔 시간을 비교해서 재상이가

   움직일 수 있는지 확인해 주어야 한다고 했다. 즉, (x, y)에 화산쇄설류가 2초에 덮치는데, 재상이가 (x, y)에 1초에

   갈 수 있다면 (x, y)는 재상이가 갈 수 있는 곳이다.

   그렇다면 화산이 있는 지점은 어떻게 판단해야할까?? 0 초로 설정하면 되지 않을까? 라고 생각해봤는데,

   본인이 Volcano_Time 맵을 만들 때, 화산이 폭팔하는 시간을 기준으로 탐색을 했기 때문에, 0초로 설정한다면

   이 시간들이 잘못 설정되었을 것이다. 이 부분 때문에 본인은 그냥 맵을 하나 더 만들었다.

   사실, 조건문 몇 개를 더 달아준다면 맵을 하나 더 만들지 않아도 될 것 같다...


[ 소스코드 ]

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
 
#define endl "\n"
#define MAX 100
#define INF 987654321
using namespace std;
 
int N, M, V;
int Sx, Sy;
int MAP[MAX][MAX];
int Volcano_Time[MAX][MAX];
int Volcano_MAP[MAX][MAX];
bool Visit[MAX][MAX];
int Highest_Pos, Shortest_Time;
 
vector<pair<pair<intint>int>> Volcano_V;
 
int dx[] = { 001-1 };
int dy[] = { 1-100 };
 
void Initialize()
{
    for (int i = 0; i < MAX; i++)
    {
        for (int j = 0; j < MAX; j++)
        {
            Volcano_Time[i][j] = INF;
        }
    }
    Highest_Pos = Shortest_Time = 0;
}
 
void Print(int A[][MAX])
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            if (Volcano_MAP[i][j] == -1)
            {
                cout << "-1" << " ";
            }
            else
            {
                cout << A[i][j] << " ";
            }
        }
        cout << endl;
    }
}
 
void Input()
{
    cin >> N >> M >> V;
    cin >> Sx >> Sy;
    Sx = Sx - 1;
    Sy = Sy - 1;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            cin >> MAP[i][j];
        }
    }
    for (int i = 0; i < V; i++)
    {
        int x, y, t;
        cin >> x >> y >> t;
        x = x - 1;
        y = y - 1;
        Volcano_MAP[x][y] = -1;
        Volcano_V.push_back(make_pair(make_pair(x, y), t));
    }
}
 
void Make_Volcano_MAP()
{
    for (int v = 0; v < Volcano_V.size(); v++)
    {
        memset(Visit, falsesizeof(Visit));
 
        int Volcano_X = Volcano_V[v].first.first;
        int Volcano_Y = Volcano_V[v].first.second;
        int Volcano_BT = Volcano_V[v].second;
 
        queue<pair<intint>> Q;
        Q.push(make_pair(Volcano_X, Volcano_Y));
        Volcano_Time[Volcano_X][Volcano_Y] = Volcano_BT;
        
        int t = Volcano_BT + 1;
        while (Q.empty() == 0)
        {
            int Qs = Q.size();
            for (int s = 0; s < Qs; s++)
            {
                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 < N && ny < M)
                    {
                        if (Volcano_Time[nx][ny] > t)
                        {
                            Volcano_Time[nx][ny] = t;
                            Q.push(make_pair(nx, ny));
                        }
                    }
                }
            }
            t++;
        }
    }
}
 
void Move_Person()
{
    queue<pair<pair<intint>int>> Q;
    Q.push(make_pair(make_pair(Sx, Sy), 0));
    Visit[Sx][Sy] = 0;
 
    while (Q.empty() == 0)
    {
        int x = Q.front().first.first;
        int y = Q.front().first.second;
        int t = Q.front().second;
        Q.pop();
 
        if (MAP[x][y] > Highest_Pos)
        {
            Highest_Pos = MAP[x][y];
            Shortest_Time = t;
        }
 
        for (int i = 0; i < 4; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            int nt = t + 1;
 
            if (nx >= 0 && ny >= 0 && nx < N && ny < M)
            {
                if (Visit[nx][ny] == false)
                {
                    Visit[nx][ny] = true;
                    if (Volcano_MAP[nx][ny] == -1continue;
                    if (Volcano_Time[nx][ny] > nt)
                    {
                        Q.push(make_pair(make_pair(nx, ny), nt));
                    }
                }
            }
        }
    }
}
 
void Solution()
{
    Make_Volcano_MAP();
    memset(Visit, falsesizeof(Visit));
    Move_Person();
}
 
void Solve()
{
    Initialize();
    Input();
    Solution();
    cout << Highest_Pos << " " << Shortest_Time << endl;
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    //freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
 
 
cs

  


+ Recent posts