Algorithms/Depth First Search

[DFS 알고리즘] 문제풀이 전략

잉숭 2021. 2. 11. 17:44

DFS는 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘이다

 

가장 깊은 부분 탐색 이후에 다시 거슬러 올라오는 과정이 필요하므로 과정을 기록할 수 있는 Stack을 주로 사용한다

 

동시에 깊이를 확인하여 다시 올라갈지 결정해야 하므로 재귀 함수를 사용한다

 

대표 예제를 통해 이를 연습해보자


문제 : N*M 크기의 얼음 틀이 존재한다. 얼음 틀 모양이 주어졌을 때 생성되는 아이스크림의 수를 구하라

 

입력 조건

  • 첫 번째 줄에 얼음 틀의 세로 길이 N과 가로 길이 M이 주어진다 (1<=N,M<=1000)
  • 두 번째 줄부터 N+1번째 줄까지 얼음 틀의 형태가 주어진다
  • 구멍이 뚫려 있는 부분은 0, 그렇지 않은 부분은 1이다

출력 조건

  • 한 번에 만들 수 있는 아이스크림의 개수를 출력한다

입력 예시 1

4 5
0 0 1 1 0
0 0 0 1 1
1 1 1 1 1 
0 0 0 0 0

출력 예시 1

3

BFS 방식으로 문제를 풀 수 있었지만 탐색하는 거리는 필요하지 않았기 때문에 DFS 방식으로 풀어 보았다

 

탐색 노드의 상하좌우를 탐색하면서 방문하지 않은 노드들을 다시 재귀적으로 탐색했다


#include<bits/stdc++.h>
#define X first
#define Y second
using namespace std;
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };
int n, m;
int ans;
int board[1001][1001];
int check[1001][1001];
void DFS(pair<int, int> p);
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 0;i < n;i++) {
        for (int j = 0;j < m;j++) {
            cin >> board[i][j];
            if (board[i][j] == 1) check[i][j] = -1;
        }
    }
    for (int i = 0;i < n;i++) {
        for (int j = 0;j < m;j++) {
            if (check[i][j] == 0) {
                DFS({ i,j });
                ans++;
            }
        }
    }
    cout << ans;
    return 0;
}

void DFS(pair<int,int> p) {
    for (int dir = 0;dir < 4;dir++) {
        int mx = p.X + dx[dir];
        int my = p.Y + dy[dir];
        if (mx < 0 || my < 0 || mx >= n || my >= m) continue;
        if (check[mx][my] != 0) continue;
        check[mx][my] = 1;
        DFS({mx,my});
    }
}