https://www.acmicpc.net/problem/4963
4963번: 섬의 개수
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도
www.acmicpc.net
걸린 시간 : 11분 3초
가장 기본적인 dfs 혹은 bfs 문제였다.
"간단한 경우에는" 큐를 써야하는 bfs와 달리 재귀를 사용하는 dfs가 구현이 더 편해 dfs로 구현한다.
하지만 알고리즘이 복잡해지거나 최단 경로를 구하는 등의 많은 경우에 bfs를 더 많이 쓰는 것 같다. 이 문제는 dfs로 풀었다.
board를 탐색하면서 섬이 발견되면 카운트해준다. 그리고 연결된 섬을 지워주는 dfs 함수를 실행시킨다. 이렇게 섬의 개수만을 세는 경우, 방문 체크를 따로 하지 않고 섬을 직접 없애는 파괴적인 코드가 더 간편하다.
추가로, board에 0 혹은 1 로만 데이터가 들어와 bool 형으로 쓸 수도 있겠지만, bool이든 int이든 메모리를 1바이트 차지하는 것은 똑같으므로 int 형을 쓰는 게 좋아보인다. 만약 vector 형으로 쓴다면 실제로 1비트만을 차지하므로 vector<vector<bool> > 형으로 쓰는 것은 효용이 있어보인다.
#include <bits/stdc++.h> using namespace std; int board[51][51]; int di[8] = {-1, -1, -1, 0, 1, 1, 1, 0}; int dj[8] = {-1, 0, 1, 1, 1, 0, -1, -1}; int w, h; void dfs (int ci, int cj) { board[ci][cj] = 0; for (int k = 0; k < 8; k++) { int ni = ci + di[k]; int nj = cj + dj[k]; if (ni < 0 || ni >= h || nj < 0 || nj >= w || board[ni][nj] == 0) continue; dfs(ni, nj); } } int main(void) { ios::sync_with_stdio(0); cin.tie(0); while(1) { int ans = 0; cin >> w >> h; if (w == 0 && h == 0) break; for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) cin >> board[i][j]; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (board[i][j] == 1) { ans++; dfs(i, j); } } } cout << ans << "\n"; } return 0; }
'Baekjoon Online Judge' 카테고리의 다른 글
[BOJ] 1912: 연속합 (C++) with 누적합 (0) | 2023.08.16 |
---|---|
[BOJ] 2644: 촌수계산 (C++) (0) | 2023.08.06 |
[BOJ] 10799 : 쇠막대기 (C++) (0) | 2023.08.06 |
[BOJ] 14500 : 테트로미노 (JAVA) with DFS (0) | 2023.08.03 |
[BOJ] 1941: 소문난 칠공주 (C++) with 조합 (0) | 2023.08.03 |