치즈
https://www.acmicpc.net/problem/2638
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
---|---|---|---|---|---|
1 초 | 128 MB | 20960 | 9751 | 7291 | 45.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번
알고리즘 분류
통과된 코드
#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; }