문제 링크입니다 https://www.acmicpc.net/problem/2667
2667번: 단지번호붙이기
<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집들의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다. <그림 2>는 <그림 1>을 단지별로 번호를 붙인 것이다. 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수
www.acmicpc.net
DFS와 BFS 중 어느 것이든 상관없는 문제였습니다. BFS를 통해 문제를 해결했고, 해결 절차는 다음과 같습니다.
[1] 입력받은 지도를 훑으면서 집이 있고, 동시에 아직 방문하지 않은 집이라면 해당 좌표부터 BFS를 시작합니다.
[2] BFS 함수를 통해 연결되어있는 집이 몇 개인지 파악하고 반환해줍니다.
[3] 반환받은 값을 배열에 저장하고, 다시 1번으로 돌아갑니다.
이렇게 반복하여 모든 집을 방문하게 되면 집이 몇 개인지를 저장한 배열을 오름차순으로 정렬한 후, BFS를 몇 번 호출 했는지 (단지가 몇 개인지) 출력하고 각 단지별 집의 개수(정렬한 배열의 값)를 순서대로 출력하면 됩니다.
[소스코드]
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
|
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX = 25 + 10;
bool check[MAX][MAX]; // 방문 처리를 할 check 배열
// 단지의 개수를 나타낼 ret, 집의 개수를 저장할 result
int n, map[MAX][MAX], ret, result[MAX*MAX];
const int dy[] = { -1,0,1,0 };
const int dx[] = { 0,-1,0,1 };
// [2] (y, x)부터 bfs를 통해 연결된 집의 개수를 세어서 반환하는 함수
int bfs(int y, int x) {
queue <pair<int, int> > q;
int cnt = 0; // 집의 개수를 세어줄 변수
check[y][x] = true; // 방문 처리
q.push(make_pair(y, x));
while (!q.empty()) {
// 현재 좌표의 y값, x값을 꺼냅니다
int cury = q.front().first, curx = q.front().second;
// pop을 한 후, 집의 개수를 늘려줍니다
q.pop(), cnt++;
// 상, 하, 좌, 우를 모두 확인하면서
for (int i = 0; i < 4; i++) {
// 다음 칸을 결정하고
int yy = cury + dy[i], xx = curx + dx[i];
// 그 칸을 이미 방문했거나, 그곳이 집이 아니거나
// 그 칸이 배열을 벗어났으면
if (check[yy][xx] || !map[yy][xx] || yy < 0 || yy >= n || xx < 0 || xx >= n)
continue; // 위로 올라갑니다
q.push(make_pair(yy, xx)); // 집인 칸을 큐에 넣고
check[yy][xx] = true; // 방문 처리
}
}
return cnt; // [2] 집의 개수 반환
}
int main(void) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
// 띄어쓰기가 되지 않은 입력이므로 1d로 받아주면
// 숫자 하나씩 입력 받을 수 있습니다
scanf("%1d", &map[i][j]);
// [1] 지도를 훑으면서
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
// [1] 해당 좌표의 값이 0이 아니고 아직 방문하지 않았으면 bfs
if (map[i][j] && !check[i][j])
result[ret++] = bfs(i, j); // [3] 반환 받은 값을 배열에 저장
sort(result, result + ret); // 배열을 오름차순으로 정렬합니다
// ret 값은 결국 0부터 bfs가 실행될때마다 1씩 증가하므로
// 최종적으로 단지의 개수가 됩니다
printf("%d\n", ret);
// 그래서 i는 0부터 ret 까지 : 단지의 개수만큼
for (int i = 0; i < ret; i++)
printf("%d\n", result[i]);
return 0;
}
|
cs |
'알고리즘 > BaekJoon' 카테고리의 다른 글
백준 1697 : 숨바꼭질 (0) | 2020.02.26 |
---|---|
백준 4963 : 섬의 개수 (0) | 2020.02.26 |
백준 1707 : 이분 그래프 (0) | 2020.02.25 |
백준 11724 : 연결 요소의 개수 (0) | 2020.02.25 |
백준 15658 : 연산자 끼워넣기 (2) (0) | 2020.02.25 |