백준 2638번 (치즈, C++) [BAEKJOON]

치즈

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

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초128 MB209609751729145.957%

문제

N×M의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다.

단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다.

이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다.

그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도

2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다.

따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.

<그림 1>

<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다.

그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다.

그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.

<그림 2>

<그림 3>

모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다.

입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오.

입력

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다.

그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고,

치즈가 없는 부분은 0으로 표시된다. 또한, 각 0과 1은 하나의 공백으로 분리되어 있다.

출력

출력으로는 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 정수로 첫 줄에 출력한다.

예제 입력 1

8 9
0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0
0 0 0 1 1 0 1 1 0
0 0 1 1 1 1 1 1 0
0 0 1 1 1 1 1 0 0
0 0 1 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

예제 출력 1

4

추가 예제

예제 입력 A

7 7
0 0 0 0 0 0 0
0 1 1 0 1 1 0
0 1 1 1 1 1 0
0 0 1 0 1 0 0
0 1 1 1 1 1 0
0 1 1 0 1 1 0
0 0 0 0 0 0 0

예제 출력 A

3

예제 입력 B

8 9
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

예제 출력 B

2

예제 입력 C

5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 1 0
0 0 0 0 0 0

예제 출력 C

1

예제 입력 D

10 10
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0
0 1 0 1 1 1 1 0 1 0
0 1 0 0 1 1 0 0 1 0
0 1 0 0 1 1 0 0 1 0
0 1 0 0 1 1 0 0 1 0
0 1 0 0 1 0 0 0 1 0
0 1 0 1 1 1 1 0 1 0
0 1 1 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 0

예제 출력 D

4

출처

Olympiad > 한국정보올림피아드 > KOI 2000 > 중등부 2번

  • 문제의 오타를 찾은 사람: apjw6112
  • 잘못된 데이터를 찾은 사람: tncks0121

알고리즘 분류


통과된 코드

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int _DxDy[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
int _MapArr[101][101];
bool _isVisited[101][101]; // 방문 체크

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    int _N, _M ,_NumCheese = 0, _Res = 0;
    cin >> _N >> _M;
    for (int i = 1; i <= _N; i++) {
        for (int j = 1; j <= _M; j++) {
            cin >> _MapArr[i][j];
            if (_MapArr[i][j]) _NumCheese++; // 치즈의 개수
        }
    }

    while (_NumCheese) { // 치즈가 0이 될때까지 반복
        _Res++; // 시간 ++
        vector<pair<int, int>> _MeltedcheeseV; // 녹을 치즈의 좌표를 저장할 벡터
        for (int i = 1; i <= _N; i++) { // 방문 초기화
            for (int j = 1; j <= _M; j++) {
                _isVisited[i][j] = false;
            }
        }
        // BFS 탐색으로 외부와 닿는 치즈를 찾는다.
        queue<pair<int, int>> myQueue;
        myQueue.push(make_pair(1, 1));
        _MapArr[1][1] = -1; // 외부와 내부의 공기를 구분
        _isVisited[1][1] = true;
        while (!myQueue.empty()) {
            pair<int, int> _CntPos = myQueue.front();
            myQueue.pop();
            for (int k = 0; k < 4; k++) { // 상하 좌우로 검색
                int nx = _CntPos.first + _DxDy[k][0];
                int ny = _CntPos.second + _DxDy[k][1];
                if (nx <= 0 || ny <= 0 || nx > _N || ny > _M) continue; // 범위를 벗어난다면 넘어간다.
                if (_isVisited[nx][ny]) continue; // 방문 했다면 넘어간다.
                _isVisited[nx][ny] = true; // 방문 처리
                if (_MapArr[nx][ny] == 1) { // 만약 치즈라면 다시 큐에 넣을 필요가 없다.
                    _MeltedcheeseV.push_back(make_pair(nx, ny));
                    continue;
                }
                _MapArr[nx][ny] = -1;
                myQueue.push(make_pair(nx, ny));
            }
        }

        for (auto& it : _MeltedcheeseV) { // 표면과 닿아있는 치즈들을 순회
            int _AirNum = 0; // 외부 공기와 닿는 수
            for (int k = 0; k < 4; k++) { // 치즈의 상하 좌우로 검색
                int nx = it.first + _DxDy[k][0];
                int ny = it.second + _DxDy[k][1];
                if (_MapArr[nx][ny] == -1) {
                    _AirNum++;
                    if (_AirNum >= 2) break; // 공기와 닿는 면적이 2이상이면 break;
                }
            }
            if (_AirNum >= 2) { // 닿는 부분이 2개 이상
                _MapArr[it.first][it.second] = 0;
                _NumCheese--; // 치즈의 개수를 줄여준다.
            }
        }

    }

    cout << _Res;
    
    return 0;
}

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤