BOJ/BFS\DFS

[C/C++] 백준 - 2638번 : 치즈

JWonK 2021. 8. 21. 13:52
728x90
반응형

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

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

문제

N×M (5≤N, M≤100)의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다. 단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다. 이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다. 그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도 2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다. 따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.

<그림 1>

<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다. 그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다. 그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.

<그림 2>

<그림 3>

모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다. 입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오

 

쉬운 BFS문제이다. 외부 공기와 내부 공기만 분리하면 되는데 맨 가장자리에는 치즈가 놓이지 않는다는 조건이 있기 

때문에 맨 가장자리에서 시작해서 갈 수 있는 곳들은 모두 들어가고 치즈를 만나면 그 치즈가 만나는 벽의 개수를 저장시켜주면 된다. 그리고 모든 탐색이 끝나고 저장해놓은 치즈가 만난 벽의 개수를 확인하여 2개 이상인 경우 그 치즈를 녹여주기만 하면 된다.

#include <iostream>
#include <list>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <bitset>
#define CUNLINK ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)

using namespace std;

int N, M;
int board[101][101];
int visited[101][101];
int Cheese[101][101];
const int dy[] = { 1,-1,0,0 };
const int dx[] = { 0,0,1,-1 };

bool isEnd() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (board[i][j] == 1) return false;
		}
	}
	return true;
}


void Melt_Cheese() {
	memset(visited, 0, sizeof(visited));
	memset(Cheese, 0, sizeof(Cheese));
	queue<pair<int, int>> q;
	q.push({ 0,0 });
	visited[0][0] = 1;
	while (!q.empty()) {
		int y = q.front().first;
		int x = q.front().second;
		q.pop();

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

			if (ny < 0 || ny >= N || nx < 0 || nx >= M) continue;
			if (visited[ny][nx]) continue;
			if (board[ny][nx] == 0) {
				visited[ny][nx] = 1;
				q.push({ ny, nx });
			}
			else if (board[ny][nx] == 1) {
				Cheese[ny][nx]++;
			}
		}
	}
}

void go_erase() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (Cheese[i][j] >= 2) {
				board[i][j] = 0;
			}
		}
	}
}

int main() {
	CUNLINK;
	cin >> N >> M;	
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> board[i][j];
		}
	}

	int Cnt = 0;
	while (1) {
		if (isEnd()) break;
		Melt_Cheese();
		go_erase();
		Cnt++;
	}
	cout << Cnt << endl;

	return 0;
}
728x90
반응형