백준 2573 - 빙산
생각 및 접근
문제를 요약하자면,
- 1의 시간이 지날 때, 상하좌우 바다의 갯수만큼 얼음이 녹는다.
- 빙하가 여러 개로 갈라지면, 그 때의 시간을 출력한다.
- 빙하가 다 녹을 때까지 여러 개로 갈라지지 않으면, 0을 출력한다.
빙하가 녹는 과정을 bfs로, 빙하가 여러 개로 갈라졌는지 확인하는 과정은 dfs로 체크한다.
바다의 정보를 저장하는
sea[302][302]
, 높이h
, 너비w
sea
를 받을 때, 1 이상이면 빙하라는 이야기므로,queue< pair<int, int> > ice;
에 좌표 정보를 넣어준다,for (int i = 1; i <= h; i++) { for (int j = 1; j <= w; j++) { cin >> sea[i][j]; if (sea[i][j] >= 1) ice.push(make_pair(j, i)); } }
bfs와 dfs를 수행한다.
while (!ice.empty()) { int iceNum = ice.size(); // 큐에 들어있는 빙하만큼만 큐 탐색 while (iceNum--) { int cnt = 0; int x = ice.front().first; int y = ice.front().second; ice.pop(); // 1의 시간이 지날 때 동시다발적으로 녹는다. // 만약 1의 시간이 지나면서, 바로 왼쪽 빙하가 다 녹아서 0이 되었다고 하면, 0이 되었다고 왼쪽 빙하때문에 내 빙하가 1이 더 줄어드는 것을 방지한다. 따라서 visit 배열을 선언해주어야 한다. visit[y][x] = 1; // 상하좌우 탐색해서 sea에서 0인 것만 cnt를 늘려준다. // cnt는 빙하가 녹을 양을 의미한다. for (int i = 0; i < 4; i++) { int xx = x + dx[i]; int yy = y + dy[i]; if (xx >= 1 && xx <= w && yy >= 1 && yy <= h && visit[yy][xx] == 0 && sea[yy][xx] == 0) { cnt++; } } sea[y][x] = max(0, sea[y][x] - cnt); // 빙하가 아직 다 녹지 않았다면 push if (sea[y][x] > 0) { ice.push(make_pair(x, y)); } } // 빙하가 몇 조각으로 나뉘었는지 찾기 memset(visit, 0, sizeof(visit)); int cnt = 0; for (int i = 1; i <= h; i++) { for (int j = 1; j <= w; j++) { if (visit[i][j] == 0 && sea[i][j] != 0) { dfs(j, i); cnt++; } } } // 조각으로 나뉘지 않고 다 녹았다. if (cnt == 0) { cout << 0; exit(0); } // 2조각 이상이다. else if (cnt != 1) { cout << answer; exit(0); } answer++; memset(visit, 0, sizeof(visit)); }
void dfs(int a, int b) { visit[b][a] = 1; for (int i = 0; i < 4; i++) { int aa = a + dx[i]; int bb = b + dy[i]; if (aa >= 1 && aa <= w && bb >= 1 && bb <= h && visit[bb][aa] != 1 && sea[bb][aa] != 0) { dfs(aa, bb); } } }
코드
#include <bits/stdc++.h>
using namespace std;
int dx[] = { -1, 0, 1, 0 };
int dy[] = { 0, -1, 0, 1 };
int sea[302][302], visit[302][302], h, w, answer = 1;
queue< pair<int, int> > ice;
void dfs(int a, int b) {
visit[b][a] = 1;
for (int i = 0; i < 4; i++) {
int aa = a + dx[i];
int bb = b + dy[i];
if (aa >= 1 && aa <= w && bb >= 1 && bb <= h && visit[bb][aa] != 1 && sea[bb][aa] != 0) {
dfs(aa, bb);
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> h >> w;
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++) {
cin >> sea[i][j];
if (sea[i][j] >= 1) ice.push(make_pair(j, i));
}
}
while (!ice.empty()) {
int iceNum = ice.size();
while (iceNum--) {
int cnt = 0;
int x = ice.front().first;
int y = ice.front().second;
ice.pop();
visit[y][x] = 1;
for (int i = 0; i < 4; i++) {
int xx = x + dx[i];
int yy = y + dy[i];
if (xx >= 1 && xx <= w && yy >= 1 && yy <= h && visit[yy][xx] == 0 && sea[yy][xx] == 0) {
cnt++;
}
}
sea[y][x] = max(0, sea[y][x] - cnt);
if (sea[y][x] > 0) {
ice.push(make_pair(x, y));
}
}
memset(visit, 0, sizeof(visit));
int cnt = 0;
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++) {
if (visit[i][j] == 0 && sea[i][j] != 0) {
dfs(j, i);
cnt++;
}
}
}
if (cnt == 0) {
cout << 0;
exit(0);
}
else if (cnt != 1) {
cout << answer;
exit(0);
}
answer++;
memset(visit, 0, sizeof(visit));
}
}
채점 결과
'Coding Test > acmicpc' 카테고리의 다른 글
백준 3190 - 뱀 (c++) (0) | 2020.09.07 |
---|---|
백준 12100 - 2048 Easy (c++) (0) | 2020.09.07 |
백준 7569 - 토마토 (c++) (0) | 2020.08.28 |
백준 2644 - 촌수계산 (c++) (0) | 2020.08.28 |
백준 5557 - 1학년 (c++) (0) | 2020.08.24 |