[백준] 2667 단지번호붙이기

김보현·2022년 2월 9일
0

코딩테스트

목록 보기
9/26

백준2667링크

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

입력

첫 번째 줄에는 지도의 크기 N(정사각형이므로 가로와 세로의 크기는 같으며 5≤N≤25)이 입력
그 다음 N줄에는 각각 N개의 자료(0혹은 1)가 입력

출력

지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력

풀이

각 단지별 BFS 탐색하여 1로 되어있는 집의 수 구하기 (DFS 풀이도 가능)
-> 단지별 시작하는 구간 찾아 반복할 수 있도록 설정
-> 찾아보니 시작점을 찾는 과정을 main함수 내에서 더 간단하게 풀이할 수 있는 방법도 있을 것 같지만 우선은 따로 함수(find_Start)를 구현

주의
그래프 바깥으로 나가는 범위 확인
if(nnx<0||nnx>=N||nny<0||nny>=N) continue;

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>

#define MAXN 25
using namespace std;

int g[MAXN+1][MAXN+1]={0,}; //그래프 배열
bool visited[MAXN+1][MAXN+1]={false,}; //방문되었는지 확인하는 배열
int N;

//상하좌우 방향
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};

vector<int> houses;

pair<int,int> find_Start(){ //단지의 시작점 확인하기
    pair<int,int> start;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            if(!visited[i][j]&&g[i][j]==1){ //방문되지 않고 1인 구간 첫 시작으로 설정
                start=make_pair(i, j);
                return start;
            }
        }
    }
    return make_pair(-1, -1);
}
int BFS(){
    int total=0;
    
    while(1){
        queue<pair<int,int>> q;
        pair<int,int> s=find_Start(); //시작점 찾기
        if(s.first==-1){ //더이상 시작점이 없는 경우
            return total;
        }else{
            total++;
            int x=s.first;
            int y=s.second;
            q.push(s);
            visited[x][y]=true;
            
            int house=1;
            
            //BFS 탐색
            while(!q.empty()){
                int nx=q.front().first;
                int ny=q.front().second;
                q.pop();
                
                for(int i=0;i<4;i++){ //상하좌우 확인
                    int nnx=nx+dx[i];
                    int nny=ny+dy[i];
                    
                    if(nnx<0||nnx>=N||nny<0||nny>=N){
                        continue;
                    }
                    if(g[nnx][nny]==0){
                        continue;
                    }
                    if(!visited[nnx][nny] && g[nnx][nny]==1){ //방문되지 않은 1로 된 구역 확인
                        q.push(make_pair(nnx,nny));
                        visited[nnx][nny]=true;
                        house++;
                    }
                }
            }
            houses.push_back(house);
        }
    }

    return total;
}

int main() {
    
    cin>>N;
    
    string s;
    for(int i=0;i < N;i++){
        cin>>s;
        for(int j=0;j<s.length();j++){
            g[i][j]=s[j]-'0';
        }
    }
    
    int result=BFS();
    cout<<result<<"\n";
    
    sort(houses.begin(),houses.end()); //오름차순으로 설정
    for(int i=0;i<houses.size();i++){
        cout<<houses[i]<<"\n";
    }
    return 0;
}
profile
📈어제보다 조금 더 성장하는 오늘을 위해

0개의 댓글