Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 이분탐색
- BOJ11066
- 백준
- DP
- BOJ11729
- BOJ14501
- 백준2110
- BOJ11404
- BOJ1931
- github_actions
- BOJ1753
- 색종이와가위
- BOJ9663
- 백트래킹
- BOJ2805
- BOJ20444
- 백준2141
- 백준 #BOJ #1697
- BOJ2629
- 1520내리막길
- BOJ14719
- 프로그래머스 #무지의먹방라이브 #C++
- 재귀
- 백준2533
- boj
- BOJ2110
- BFS
- html
- 백준11404
- 생활코딩
Archives
- Today
- Total
poksul_log
# 2573. 빙산 본문
관련 알고리즘 : 구현, 그래프 탐색
문제 링크 : https://www.acmicpc.net/problem/2573
2573번: 빙산
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을
www.acmicpc.net
문제 풀이
문제의 조건을 보면,
- 2차원 배열의 행(N, 3<=N<=300) 과 열(M, 3<=M<=300)
- 빙산의 높이 : 각 칸의 양의 정수 숫자 표시 (0~10 사이의 정수)
- 바다 : 0으로 표시
- 매 년 빙산이 줄어드는 높이 = 해당 빙산을 둘러싸고 있는 바다가 있는 칸(숫자가 0인 칸)의 개수
- 덩어리의 기준 : 동서남북 방향 중 어느 한 방향 이상으로 붙어있는 빙산이 존재하면 한 덩어리
빙산이 두 덩어리 이상으로 분리되는 최초의 시간을 구하는 것이 문제의 목적이다.
- 바다와 접해있는 빙산 주변 바다 칸 수만큼 높이 차감.
- 2차원 배열을 돌면서 빙산이 있는 칸(0이 아닌 칸) 탐색 => BFS 이용
- 연결되어 있는 지점들을 돌며 방문, 방문 후 체크 => ( BFS 호출 수 = 빙산의 덩어리 수 )
0 | 2 | 3 |
1 | 0 | 0 |
3 | 4 | 5 |
주의할 점 : 2차원 배열을 한 칸씩 돌며 빙산을 녹이면 안 됨!
위 표에 있는 경우를 보면,
▶ 높이가 2인 빙산(빨간색 표시)를 먼저 녹이는 경우, 2면이 바다와 맞닿아 있기 때문에 1년 후 높이가 0이 된다.
▶ 그 이후 높이가 3인 빙산(빨간색 표시)를 녹이면, 2면이 바다와 맞닿게 되기 때문에 높이가 1이 된다.
하지만 정확히는 1년 후
▶ 높이가 2인 빙산은 0으로, 높이가 3인 빙산은 2가 되어야 한다.
c++ 코드
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
int n, m;
int map[300][300];
int temp[300][300]; // 바다로 인해 차감되는 빙산의 높이 한번에 계산 방지용 배열
bool visit[300][300];
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };
void Input()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> map[i][j];
}
}
}
void BFS(int a, int b)
{
queue<pair<int, int>> Q;
Q.push(make_pair(a, b));
visit[a][b] = true;
while (Q.empty() == 0)
{
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 (visit[nx][ny] == false && map[nx][ny] != 0)
{
visit[nx][ny] = true; // 방문 check
Q.push(make_pair(nx, ny));
}
}
}
}
}
int Melt(int x, int y)
{
int cnt = 0;
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (map[nx][ny] == 0) cnt++; // 주변 바다의 개수만큼 cnt ++
}
return cnt;
}
void Solution()
{
int year = 0;
while (1)
{
int ice = 0;
memset(visit, false, sizeof(visit));
memset(temp, 0, sizeof(temp));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (map[i][j] != 0 && visit[i][j] == false) // 빙산이 있고, 아직 방문하지 않았다면
{
// bfs 한번 돌 때마다 연결된 덩어리 빙산 1개씩 추가
ice++;
BFS(i, j);
}
}
}
if (ice >= 2) { cout << year << "\n"; break; }
if (ice == 0) { cout << 0 << "\n"; break; }
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (map[i][j] != 0)
{
temp[i][j] = map[i][j] - Melt(i, j); // 저장되어있는 차감높이값 한번에 빼주기
if (temp[i][j] < 0) temp[i][j] = 0;
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
map[i][j] = temp[i][j];
}
}
year++;
}
}
void Solve()
{
Input();
Solution();
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
Solve();
return 0;
}
'Coding Test > BOJ' 카테고리의 다른 글
# 7576. 토마토 (0) | 2023.04.02 |
---|---|
# 9205. 맥주 마시면서 걸어가기 (0) | 2023.03.26 |
# 16197. 두 동전 (0) | 2023.03.05 |
# 2141. 우체국 (0) | 2023.02.26 |
# 15961. 회전 초밥 (0) | 2023.02.05 |