알고리즘/문제 풀이

백준 4963 - 섬의 개수(C++)

qqlzzb 2022. 6. 19. 13:41

문제 https://www.acmicpc.net/problem/4963

백준에서 그래프 탐색 알고리즘 문제를 찾아보면 같은 방법으로 풀 수 있는 유사한 문제가 많다.(2667, 1012..)

 

풀이

DFS를 이용하여 풀 수 있는 문제이다. 유의할 점은 상하좌우뿐만 아니라 대각선으로 연결된 것까지 인접했다고 보므로, 상하좌우, 4방향의 대각선까지 8방향을 전부 탐색해야 한다.

따라서 배열 dx 와 dy를 선언하여 각 좌표에 더해줌으로써 8방향을 전부 확인할 수 있다.

이때 탐색하려는 좌표가 map의 범위를 넘어가지 않는지를 확인해줘야 한다.

 

배열을 돌다가 방문하지 않았고, map의 값이 1인 좌표를 만나면 dfs를 수행한다. 이 좌표에서부터 DFS를 수행하고 함수가 종료되면 인접한 좌표를 다 탐색했다는 것이므로 cnt를 증가한다.

마지막으로 사용한 배열(visited, map)을 0으로 초기화해야 한다.

 

코드

#include <iostream>
using namespace std;

int w,h;
bool visited[50][50];
int map[50][50];
//상하좌우대각선 위치 좌표
int dx[8] = {0,1,0,-1,1,1,-1,-1};
int dy[8] = {-1,0,1,0,-1,1,1,-1};

void dfs(int x, int y)
{
    for(int i=0; i<8; i++)
    {
        int rx = x+dx[i];
        int ry = y+dy[i];

        if(rx>=h || rx<0 || ry>=w || ry<0) continue;//map의 범위를 넘어설 경우

        if(!visited[rx][ry]&&map[rx][ry]==1)
        {
            visited[rx][ry]=true;
            dfs(rx,ry);
        }
    }
}

int main()
{
    while(1)
    {
        int cnt=0;
        cin>>w>>h;
        if(w==0 && h==0) break;
        for(int i=0; i<h; i++)
        {
            for(int j=0; j<w; j++)
            {
                int a;
                cin>>a;
                map[i][j]=a;
            }
        }

        for(int i=0; i<h; i++)
        {
            for(int j=0; j<w; j++)
            {
                if(!visited[i][j]&&map[i][j]==1)
                {
                    visited[i][j];
                    dfs(i,j);
                    cnt++;
                }
            }
        }

        for(int i=0; i<h; i++) //map과 visited 배열을 초기화
        {
            for(int j=0; j<w; j++)
            {
                visited[i][j]= false;
                map[i][j]=0;
            }
        }
        cout<<cnt<<'\n';
    }
}