https://www.acmicpc.net/problem/2667

 

2667번: 단지번호붙이기

<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집들의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다. <그림 2>는 <그림 1>을 단지별로 번호를 붙인 것이다. 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수

www.acmicpc.net

플러드 필 문제중 한개이다.

 

연결요소 문제와 유사하게 방문하지 않은 정점을 찾아서 dfs / bfs 순회를 해주면 된다.

 

여기서 정점의 정보는 [행,열]이 된다. 즉, (x,y)값을 한개의 정점으로 생각하면 됨.

 

그리고 이런 문제에서는 인접 정점을 찾는 방법은 아래와 같이 한개 정점 (x,y)에서 위/아래/좌/우로 이동을 위해 변경되야할 좌표값을 아래 배열과 같이 넣어두고 for문을 돌리면 간단하게 구현 할 수 있다.

 

int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };

 

연속된 숫자중 1개 자리씩만 입력을 받고 싶을경우 아래 코드를 이용하면 된다.

scanf("%1d", &input[i][j]);

 

 

아래 소스코드는 bfs를 사용해서 해결하였다.

 

#include <bits/stdc++.h>
using namespace std;

int input[30][30];
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
int n;
int res[25 * 25];
#define Dangi_Start_Num 2  //플러드 필에 사용되는 단지 시작 번호
void bfs(int x, int y, int cnt) {
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    input[x][y] = cnt;

    while (!q.empty()) {
        x = q.front().first;
        y = q.front().second;
        q.pop();
        for (int k = 0; k < 4; k++) {
            int nx = x + dx[k];
            int ny = y + dy[k];
            if (0 <= nx && nx < n && 0 <= ny && ny < n) {  //input 배열의 범위밖을 참조하지 않도록 하기 위해
                if (input[nx][ny] == 1) {
                    q.push(make_pair(nx, ny));
                    input[nx][ny] = cnt;
                }
            }
        }
    }
}
int main() {

    //지도 정보 입력 받기
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%1d", &input[i][j]);
        }
    }
    //플러드 필
    int cnt = Dangi_Start_Num;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (input[i][j] == 1) {
                bfs(i, j, cnt++);
            }
        }
    }
    //단지 개수 출력
    printf("%d\n", cnt - Dangi_Start_Num);
    
    //플러드 필된 값(즉, 단지번호) 별로 몇개가 있는지 개수를 셈
    //그 개수를 res배열에 index는 단지배열이고, 그곳에 그 단지의 개수를 저장해둠.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (input[i][j] != 0)
                res[input[i][j] - Dangi_Start_Num] += 1;
        }
    }
    //res를 오른 차순으로 정렬함.
    sort(res, res + cnt - Dangi_Start_Num);
    //단지별 개수를 오름차순으로 출력함.
    for (int i = 0; i < cnt - Dangi_Start_Num; i++) {
        printf("%d\n", res[i]);
    }

    return 0;
}

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - A/B : 1008번  (0) 2019.12.19
백준 - 개 : 10172번  (0) 2019.12.19
백준 - 연결 요소의 개수 : 11724번  (0) 2019.12.18
백준 - 윤년 : 2753번  (0) 2019.12.18
백준 - 고양이 : 10171번  (0) 2019.12.18

+ Recent posts