백준/탐색

[백준] C++ 2636번(치즈)

2zreal 2024. 7. 16. 15:29

첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력하는 문제이다.(전형적인 BFS문제)

 

문제 해결 방법

1. 노출된 치즈의 위치 판별하기

2. 노출된  치즈를 녹이기

3. 위 과정을 치즈가 다 녹을 때까지 반복

 

노출된 치즈의 위치를 판별하기만 하면 풀리는 문제이다.

노출된 치즈의 위치를 어떻게 판별할까??

문제에 보면 가장자리에는 X표시가 되어있다는 사실을 알 수 있다. 가장자리에는 치즈를 놓지 않는다는 말이다.

즉 가장자리의 어떠한 부분에서 시작해서 치즈를 만날 때까지 너비우선탐색 해주면 치즈의 위치를 찾을 수 있다는 말이다.

무한 루프 방지를 위해 visited를 통해 방문했던 장소를 저장하고 만약 그곳이 치즈였다면 1을 0으로 수정.

치즈가 다 녹을 때까지 위 과정을 반복해 주면 끝난다.

 

#include <iostream>
#include <queue>

using namespace std;

int arr[101][101];
queue <pair<int,int> > Q;
int row[4]={-1,1,0,0};
int col[4]={0,0,-1,1};

int BFS();

int a=0;
int b=0;

int main(void)
{
	
	cin>>a>>b;
	
	int sum=0;
	int count=0;
	int page=0;
	
	for(int i=0; i<a; i++)
	{
		for(int j=0; j<b; j++)
		{
			cin>>arr[i][j];
			if(arr[i][j]==1)
			{
				sum++;
			}
		}
	}
	
	while(true)
	{
		int temp=BFS();
		count+=temp;
		page++;
		
		
		if(count==sum)
		{
			cout<<page<<endl;
			cout<<temp;
			break;
		}
	}
	
	return 0;
}

int BFS()
{
	int visited[101][101]={0};
	
	int count=0;
	
	Q.push(make_pair(0,0));
	
	while(!Q.empty())
	{
		int num1=Q.front().first;
		int num2=Q.front().second;
		
		Q.pop();
		for(int i=0; i<4; i++)
		{
			if(visited[num1+row[i]][num2+col[i]]==0&&num1+row[i]>-1&&num1+row[i]<a&&num2+col[i]>-1&&num2+col[i]<b)
			{
				visited[num1+row[i]][num2+col[i]]=1;

				if(arr[num1+row[i]][num2+col[i]]==0)
				{
					Q.push(make_pair(num1+row[i],num2+col[i]));
				}
				else
				{
					count++;
					arr[num1+row[i]][num2+col[i]]=0;
				}
				
			}
		}
	}
	
	return count;
}