코딩 테스트 준비! (백준)/BFS

[BFS] 백준 2667번 단지 번호 붙이기(C++)

lee-soo 2025. 4. 23. 19:23

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

 

 

 

[DFS,BFS] 백준 1260번 BFS와 DFS(C++)

 

이문제, 당연히 BFS와 DFS 문제를 풀고 와야 겠지?

 

내용 자체는 쉽다

그림으로만 딱 봐도 보이잖나?

그럼 어떻게 풀까?

 

앞선 BFS나 DFS문제들에선 연결된 NODE들을 통해서 그래프를 그렸는데 이번에도 똑같다

연결된 노드들끼리의 배열이 아닌 연결된 노드들의 갯수만 보면 됨~

 

 

하지만 앞선 문제들은 모두 1차원인데 이건 2차원이다

 

그럼 어떻게 풀까?

 

1. 2차원으로

2. 1차원으로

 

뭔가 반대가된 기분이네

쨋든

 

2차원으로 푸는건 쉽다

bfs 와 dfs로 들어갔을 때 , 그저 queue<pair<int,int>> q 만 새로 해줘서

쌍으로 저장하면 되지만

 

나는 그걸 몰랐다

풀고나서, 인터넷 찾아보니까 저런게 있더라

기본기가 부족한 나는 멍청이

 

난 1차원으로 풀었다

 

배열의 경우 n*n 배열에서

for(i<n)

for(j<n)

이중 중첩문을 통해 들어갔을때,

각각의 배열 원소는 i*n+j잖나

 

뭐 이건 그렇다치고

 

우리가 중요하게 생각해야 할것은

그래프를 떠올리는 것 또한 중요하지만

 

맞닿은 집들끼리 "연결" 해주는 것이 중요하다.

 

코드로 보여주겠다

 

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
bool visited[25 * 25];
vector<int> home[25 * 25];
vector<int> list;
int whole = 0;
int arr[25 * 25];
int n;
void bfs(int alpha);
int main()
{

    cin >> n;

    for (int i = 0; i < n; i++)
    {
        string temp;
        cin >> temp;
        for (int j = 0; j < n; j++)
        {
            arr[i * n + j] = temp[j] - '0';
        }
    }

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int x = i * n + j;
            if (arr[x])
            {
                if (((x + 1) % n) != 0 && arr[x + 1])
                {
                    home[x].push_back(x + 1);
                    home[x + 1].push_back(x);
                }
                if (!(((x + n) > n * n)) && arr[x + n])
                {
                    home[x].push_back(x + n);
                    home[x + n].push_back(x);
                }
            }
        }
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int temp = i * n + j;
            if (!visited[temp] && arr[temp] == 1)
                bfs(i * n + j);
        }
    }
    sort(list.begin(), list.end());
    cout << whole << "\n";
    for (int i = 0; i < list.size(); i++)
        cout << list[i] << "\n";
}
void bfs(int alpha)
{

    queue<int> p;
    p.push(alpha);
    int count_ = 1;
    visited[alpha] = true;
    whole++;
    while (!p.empty())
    {
        int temp = p.front();
        p.pop();
        for (int k = 0; k < home[temp].size(); k++)
        {
            if (!visited[home[temp][k]])
            {
                visited[home[temp][k]] = true;
                p.push(home[temp][k]);
                count_++;
            }
        }
    }
    list.push_back(count_);
}

 

 if (arr[x])
            {
                if (((x + 1) % n) != 0 && arr[x + 1])
                {
                    home[x].push_back(x + 1);
                    home[x + 1].push_back(x);
                }
                if (!(((x + n) > n * n)) && arr[x + n])
                {
                    home[x].push_back(x + n);
                    home[x + n].push_back(x);
                }
            }
여기서 보면 알겠지만 arr[x]가 1인 상태에서,
오른쪽 혹은 아래쪽으로 이동하는 것인데
만약 오른쪽으로 옮기고 n으로 나눈 나머지가 0이라면, arr[x]는 맨 오른쪽 끝번이였던 것이고
아래 조건문은 x+n ( 즉 한 칸 바로 아래 )이 전체 크기보다 클때만 고려하면 된다
 
그리고 왜 오른쪽과 아래만하고 , 왼쪽과 위쪽은 안했는가? 라고 생각한다면
 home[x].push_back(x + 1);
home[x + 1].push_back(x);
이렇게 양쪽다 해주고, i와 j가 0부터 증가하니까 이전것은 자동으로 들어가고 고려할 필요가 없다.
 
난 bfs로 풀었는데 dfs로 풀어보쇼