아카이빙/BOJ

백준 2468번 - 안전 영역

셩님 2017. 8. 13. 04:02

백준 2468번 - 안전 영역

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

문제

  • 재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다.

  • 먼저 어떤 지역의 높이 정보를 파악한다.

  • 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 안전한 영역이 최대로 몇 개가 만들어 지는 지를 조사하려고 한다.

  • 이 때, 문제를 간단하게 하기 위하여, 장마철에 내리는 비의 양에 따라 일정한 높이 이하의 모든 지점은 물에 잠긴다고 가정한다.

  • 어떤 지역의 높이 정보는 행과 열의 크기가 각각 N인 2차원 배열 형태로 주어지며 배열의 각 원소는 해당 지점의 높이를 표시하는 자연수이다.

  • ( 중략 ) 자세한 내용은 2468번 링크 참조

  • 어떤 지역의 높이 정보가 주어졌을 때, 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 계산하는 프로그램을 작성하시오.

입력

  • 첫째 줄에는 어떤 지역을 나타내는 2차원 배열의 행과 열의 개수를 나타내는 수 N이 입력된다.

  • N은 2 이상 100 이하의 정수이다.

  • 둘째 줄부터 N 개의 각 줄에는 2차원 배열의 첫 번째 행부터 N번째 행까지 순서대로 한 행씩 높이 정보가 입력된다.

  • 각 줄에는 각 행의 첫 번째 열부터 N번째 열까지 N 개의 높이 정보를 나타내는 자연수가 빈 칸을 사이에 두고 입력된다.

  • 높이는 1이상 100 이하의 정수이다.

출력

  • 첫째 줄에 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 출력한다.


접근

  • DFS와 Flood Fill을 활용하여 푼다.

  • 현재 위치에서 상하좌우의 위치를 재귀적으로 방문한다.

  • 방문한 위치가 이미 방문했던 곳이거나 높이가 강수량으로 잠기는 높이(h) 이하이면 방문하지 않는다.

  • 방문할 수 있는 영역을 모두 카운트한 다음, 높이(h)에 따라 가장 많은 안전 영역이 생기는 값이 정답.

  • 높이의 비교는 모든 높이를 비교할 필요 없기 때문에 입력된 지역의 최소, 최대값을 미리 구하고 [최소, 최대) 구간으로만 비교한다.

  • 비가 내리지 않는 경우를 고려하여 정답의 최소값은 1이다.

C++ Code

#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

int a[100][100];
int visited[100][100];
int n;
int cnt = 0;
int dx[] = { 1, 0, -1, 0 };
int dy[] = { 0, 1, 0, -1 };

void dfs(int x, int y, int h) {
    if (x >= n || y >= n || x < 0 || y < 0)
        return;

    if (visited[y][x] || a[y][x] <= h)
        return;

    visited[y][x] = true;

    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        dfs(nx, ny, h);
    }
}

int main(void) {
    int minvalue = 987654321, maxvalue = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &a[i][j]);
            minvalue = min(minvalue, a[i][j]);
            maxvalue = max(maxvalue, a[i][j]);
        }
    }

    int ans = 1;
    for (int i = minvalue; i < maxvalue; i++) {
        cnt = 0;
        for (int j = 0; j < 100; j++) fill_n(visited[j], 100, false);

        for (int y = 0; y < n; y++) {
            for (int x = 0; x < n; x++) {
                if (!visited[y][x] && a[y][x] > i) {
                    dfs(x, y, i);
                    cnt++;
                }
            }
        }
        ans = max(ans, cnt);
    }

    printf("%d\n", ans);

    return 0;
}

'아카이빙 > BOJ' 카테고리의 다른 글

백준 1629번 - 곱셈  (0) 2017.09.01
백준 1260번 - DFS와 BFS  (2) 2017.08.13
백준 1697번 - 숨바꼭질  (0) 2017.08.13
백준 1600번 - 말이 되고픈 원숭이  (1) 2017.08.13
백준 1197번 - 최소 스패닝 트리  (0) 2017.08.10