티스토리 뷰

728x90

백준 1012. 유기농 배추 (Silver II)

Type : dfs

 

문제

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다.

(한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있다고 간주한다)

한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다.

예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다.

(0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.)

 

 

입력

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 첫째 줄에는 배추를 심은 배추밭의 가로길이 M(1 ≤ M ≤ 50)과 세로길이 N(1 ≤ N ≤ 50), 그리고 배추가 심어져 있는 위치의 개수 K(1 ≤ K ≤ 2500)이 주어진다. 그 다음 K줄에는 배추의 위치 X(0 ≤ X ≤ M-1), Y(0 ≤ Y ≤ N-1)가 주어진다.

 

출력

각 테스트 케이스에 대해 필요한 최소의 배추흰지렁이 마리 수를 출력한다.

 

예제 입력 및 예제 출력

 

풀이

당분간은 dfs, bfs 위주로 문제를 풀어보려 한다. 어디서 들었는데, 알고리즘 실력을 빠른 시간 내에 올리고 싶다면, 문제를 유형별로 많이 풀어서 유형에 익숙해지는 것이 도움된다고 하더라. 그래서 이번에는 dfs 문제를 풀어보았다.

 

저번에 풀었던 2178. 미로 탐색과 비슷한데, 그 문제는 bfs 유형이었다. 이 문제는 다음 2가지에 신경을 써주어야 한다.

 

1. 행은 y축, 열은 x 축이라는 점

2. 배추들의 위치들이 구역별로 나뉘어있다는 점

3. 격자 위에서 동, 서, 남, 북으로 1칸 이내에 인근 배추가 있을 수 있다는 점

 

이때, 배추 흰 지렁이가 한 구역을 다 커버할 수 있으므로, 결국 격자 위에 배추 구역이 몇 개나 있는지를 구하면 되는 문제이다. 이때 dfs를 이용해 탐색하고자 하는 배추가 이미 탐색한 구역의 배추인지를 확인하면 된다.

 

따라서 위 내용을 기반으로 다음과 같이 코드를 구현해주면 된다.

 

1. 배추 위치 기록

행을 y축, 열을 x축으로 하여 배열에 배추의 위치를 표기해준다. 즉 다음과 같이 표기해줄 수 있다.

a[y][x] = 1;

 

2. 배추 전수 조사

전체 행렬 칸을 전수 조사하여 배추가 있는지 확인하고, 만약 배추가 있을 경우 아직 조사하지 않은 구역이라면 dfs를 통해 주변에 다른 배추가 있는지 조사해준다.

 

3. 주변으로 이동

주변에 다른 배추가 있는지 조사하기 위해 동, 서, 남, 북으로 움직인다. 이때 동, 서, 남, 북은 2차원 배열의 관점에서 다음과 같이 표현할 수 있다.

 

동 : (0, 1)

서 : (0, -1)

남 : (1, 0)

북 : (-1, 0)

 

따라서 for문을 이용해 동, 서, 남, 북으로 (총 4차례) 이동한 좌표를 계산해준다.

 

4. 이동한 위치의 배추 및 그 주변을 조사

만약 이동한 위치에 배추가 있다면 조사 완료 (방문) 표시를 해주고, dfs를 통해 그 주변을 다시 조사해준다. 더 이상 주변에 배추가 없을 때까지 계속 이를 반복해준다.

 

아직 방문하지 않은 배추를 발견할 때마다 애벌레의 수가 1씩 증가된다. 만약 같은 구역 내에서 이미 방문한 배추를 한번 더 방문하게 되더라도, 이전의 배추가 주변을 조사하면서 방문 처리를 했기 때문에 dfs 함수에서 false를 반환해 애벌레의 수가 증가하지 않는다. 

 

/*
* Author : Kwangrok Baek (zester926@gmail.com)
* memory, time : 2020 KB, 0ms
* URL : https://www.acmicpc.net/problem/1012
* type : dfs
*/

#include <iostream>
#include <cstring>

using namespace std;

int n , m, cabbage;
bool a[51][51];
bool check[51][51];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

bool dfs(int y, int x) {
    if (check[y][x]) return false;
    check[y][x] = true;
    
    for (int i = 0; i < 4; i++) {
        int next_x = x + dx[i]; // 3. 동, 서, 남, 북으로 1칸씩 이동
        int next_y = y + dy[i];

        if (next_x >= 0 && next_y >= 0 && next_x < m && next_y < n && a[next_y][next_x]) // 4. 인근 지역에 배추 있을 경우, 해당 지역 방문 처리
        dfs(next_y, next_x);
    }
    return true;
}

int main(void) {
    int TC;
    scanf("%d", &TC);
    for (int i = 0; i < TC; i++) {
        scanf("%d %d %d", &m, &n, &cabbage);
        memset(a, 0, sizeof(a));
        memset(check, 0, sizeof(check));

        for (int j = 0; j < cabbage; j++) {
            int x = 0, y = 0;
            scanf("%d %d", &x, &y);
            a[y][x] = 1; // 1. 행 - y축, 열 - x축
        }

        int bug_count = 0;

        for (int j = 0; j < n; j++) {
            for (int k = 0; k < m; k++) {
                if (a[j][k] && !check[j][k]) { // 2. 탐색 안한 구역일 경우, dfs 수행 & count 추가 
                    if (dfs(j, k)) bug_count++;
                }
            }
        }
        printf("%d\n", bug_count);
    }
}

 

 

zester926/Algorithm-challenge

알고챌 (알고리즘 챌린지) : 주 4회 알고리즘 풀이. Contribute to zester926/Algorithm-challenge development by creating an account on GitHub.

github.com

 

728x90