일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- BFS
- springboot
- boj2252
- boj15954
- boj_15684
- 동적계획법
- backtracking
- euclideanalgorithm
- mysql
- DP
- nestedjson
- TDD
- boj10942
- onTouchListner
- boj10775
- django
- boj15998
- DFS
- testdb
- react
- Spring
- boj_15685
- boj2239
- boj7579
- onTouch
- bruteforce
- boj15683
- boj15654
- DynamicProgramming
- BOJ
- Today
- Total
이마닷의 블로그
[BOJ] 2573:빙산 본문
0. 문제
https://www.acmicpc.net/problem/2573
2573번: 빙산
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 나타내는 M개의 정수가 한 개의 빈 칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0 이상 10 이하이다. 배열에서 빙산이 차지하는 칸의 개수, 즉, 1 이상의 정수가 들어가는 칸의 개수는 10,000 개 이하이다. 배열의 첫 번째 행과 열, 마지
www.acmicpc.net
1. 문제분석
- 한 칸(노드)에서 시작해서 상하좌우로 인접한 칸을 연속해서 탐색한다는 점에서 DFS 또는 BFS 알고리즘을 사용해 문제를 풀어야 함을 알 수 있다. 별다르게 최단경로를 파악할 필요는 없으므로, DFS나 BFS 둘 다 크게 상관 없을 듯 하지만, 이번에는 DFS를 사용했다.
2. 주의할 점
- 문제를 성급히 읽으면 단순히 빙산이 다 녹을때까지의 연수만 계산하는 알고리즘을 짜게된다. 하지만 구해야 하는 것은 "두 덩어리 이상으로 분리되는 최초의 시간"임을 명심하자.
- 단순히 칸 별 값이 0일 때 dfs를 call 하지 않는 것 만으로는 부족하다. 왜냐하면 dfs 함수를 진행하면서, 원래는 빙산이 다 녹지 않았지만(값이 0이 아니었지만), 해당 연도 도중에 0값이 되어버리는 칸도 있기 때문이다. 따라서 방문배열(vtd)를 별도로 사용해준다.
3. 소스코드(C++)
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#define endl '\n'
#define INF 987654321
using namespace std;
typedef pair<int, int> ii;
int n, m, cnt;
int grid[301][301];
bool vtd[301][301];
int dy[4] = { 0,1,0,-1 };
int dx[4] = { 1,0,-1,0 };
void dfs(int y, int x) {
vtd[y][x] = true;
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || ny >= n || nx < 0 || nx >= m) continue;
if (vtd[ny][nx]) continue;
if (grid[ny][nx] == 0) grid[y][x] = max(0, grid[y][x] - 1);
else dfs(ny, nx);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int ans = -1;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> grid[i][j];
}
}
while (true) {
cnt = 0;
ans++;
memset(vtd, false, sizeof(vtd));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 0 || vtd[i][j]) continue;
dfs(i, j);
cnt++;
}
}
if (cnt != 1) break;
}
if (cnt == 0) cout << 0;
else cout << ans;
return 0;
}
4. 여담
- dfs를 통해서 연결된 집단 개수를 파악한다는 점에서 boj2667 단지번호붙이기와 문제 풀이 방식이 비슷하다.
- 또한 상하좌우에 위치한 노드 값에 따라 현재 위치 값이 변화한다는 점에서 boj2636 치즈와도 문제 풀이 방식이 비슷하다.
'problem-solving' 카테고리의 다른 글
[BOJ] 1068:트리 (0) | 2020.12.10 |
---|---|
[BOJ] 12865:평범한 배낭 (0) | 2020.12.08 |
[BOJ] 2116:주사위 쌓기 (0) | 2019.09.22 |
[BOJ] 2643:색종이 올려 놓기 (0) | 2019.09.15 |
[BOJ] 1162:도로포장 (0) | 2019.09.07 |