득이공간

[백준 C++] 2638 치즈 - 너비우선탐색 본문

PS/알고리즘 문제풀이

[백준 C++] 2638 치즈 - 너비우선탐색

쟁득 2024. 3. 17. 18:40
 

2638번: 치즈

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

www.acmicpc.net

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

int N, M;
bool Cheeze[100][100];

const int DX[4] = { -1, 0, 1, 0 };
const int DY[4] = { 0, -1, 0, 1 };

queue<pair<int, int>> SQ;
bool Visited[100][100];
int Air[100][100];

void BFS()
{
	memset(Visited, false, sizeof(Visited));
	memset(Air, 0, sizeof(Air));

	Visited[0][0] = true;
	SQ.emplace(0, 0);
	while (!SQ.empty())
	{
		int R = SQ.front().first;
		int C = SQ.front().second;
		SQ.pop();
		
		for (int i = 0; i < 4; ++i)
		{
			int NR = R + DY[i];
			int NC = C + DX[i];

			if (NR < 0 || NR > N - 1
				|| NC < 0 || NC > M - 1
				|| (!Cheeze[NR][NC] && Visited[NR][NC]))
			{
				continue;
			}

			if (Cheeze[NR][NC])
			{
				++Air[NR][NC];
			}
			else
			{
				Visited[NR][NC] = true;
				SQ.emplace(NR, NC);
			}
		}
	}
}

void DeleteCheeze()
{
	BFS();

	for (int i = 1; i < N - 1; ++i)
	{
		for (int j = 1; j < M - 1; ++j)
		{
			if (Air[i][j] >= 2)
			{
				Cheeze[i][j] = false;
			}
		}
	}
}

bool HaveCheeze()
{
	for (int i = 1; i < N - 1; ++i)
	{
		for (int j = 1; j < M - 1; ++j)
		{
			if (Cheeze[i][j])
			{
				return true;
			}
		}
	}

	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

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

	int Time = 0;
	while (HaveCheeze())
	{
		DeleteCheeze();
		++Time;
	}

	cout << Time;
}

 

매 시간마다 공기에 노출된 치즈가 녹는 상황을 구현하는 문제입니다.

 

공기에 노출된 치즈 칸을 결정하는 조건은 두 개 이상의 외부 빈칸과 접촉할 때입니다.

이 말은 즉 내부에 존재하는 빈칸과는 접촉해도 개수에 카운팅 되지 않음을 뜻합니다.

 

따라서 매 시간마다 두 개 이상의 외부의 빈칸과 접촉한 치즈 칸을 골라서 해당 칸을 빈칸으로 만들어주어야 합니다.

이 때 종이의 가장자리는 무조건 빈칸(외부)이므로,

0,0 칸부터 너비 우선 탐색을 시작해서 탐색 큐에 인접한 빈칸(무조건 외부임)을 계속 넣어줍니다.

그리고 탐색 큐의 각 칸들이 인접한 치즈 칸을 만났을 때마다 해당 치즈 칸의 카운팅을 늘려줍니다.

탐색을 종료하고나면, 종이에서 2개 이상 카운팅된 치즈 칸들을 모두 빈칸으로 만들어주면 됩니다.