문제
아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓여 있지 않으며 치즈에는 하나 이상의 구멍이 있을 수 있다.
이 치즈를 공기 중에 놓으면 녹게 되는데 공기와 접촉된 칸은 한 시간이 지나면 녹아 없어진다. 치즈의 구멍 속에는 공기가 없지만 구멍을 둘러싼 치즈가 녹아서 구멍이 열리면 구멍 속으로 공기가 들어가게 된다. <그림 1>의 경우, 치즈의 구멍을 둘러싼 치즈는 녹지 않고 ‘c’로 표시된 부분만 한 시간 후에 녹아 없어져서 <그림 2>와 같이 된다.

<그림 1> 원래 치즈 모양
다시 한 시간 후에는 <그림 2>에서 ‘c’로 표시된 부분이 녹아 없어져서 <그림 3>과 같이 된다.

<그림 2> 한 시간 후의 치즈 모양

<그림 3> 두 시간 후의 치즈 모양
<그림 3>은 원래 치즈의 두 시간 후 모양을 나타내고 있으며, 남은 조각들은 한 시간이 더 지나면 모두 녹아 없어진다. 그러므로 처음 치즈가 모두 녹아 없어지는 데는 세 시간이 걸린다. <그림 3>과 같이 치즈가 녹는 과정에서 여러 조각으로 나누어 질 수도 있다.
입력으로 사각형 모양의 판의 크기와 한 조각의 치즈가 판 위에 주어졌을 때, 공기 중에서 치즈가 모두 녹아 없어지는 데 걸리는 시간과 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 치즈가 없는 칸은 0, 치즈가 있는 칸은 1로 주어지며 각 숫자 사이에는 빈칸이 하나씩 있다.
출력
첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력한다.
접근 방식
처음에는 항상 그랬듯 치즈에서 BFS를 돌 생각이였다
근데 치즈는 구멍이 있을 수 있고 구멍과 만나는 치즈는 녹지 않으니
구멍을 어떻게 구별해야할까가 고민이였다
아무리 생각해도 답이 나지 않아 다른 사람들의 해설을 찾아보았고..!
생각의 전환으로
공기에서 BFS를 돌리면 된다는 것을 깨달았다!
일단 공기는 무조건 0,0에서 시작하고
공기들은 연결이 되어있기 때문에!
그리고 공기와 구멍은 연결되어 있지 않으므로
공기와 만나는 치즈들을 녹여주면 되는 간단한 문제였다!
풀이 자체는 일반 BFS랑 다를 게 없이 정말 간단했지만
약간 빙하문제랑 비슷하다는 착각에 빠져 치즈를 가지고만 BFS를 돌리려고 했던 것이 폐착이다..!
하지만 이제 알았으니 다음에 더 잘풀겠지 :)
코드
#include<bits/stdc++.h>
using namespace std;
int N,M;
int mat[102][102];
bool visited[102][102];
int dx[4]={1,0,-1,0};
int dy[4] = {0,1,0,-1};
int meltingTime = 0, ans;
bool BFS() {
int cnt = 0;
queue<pair<int,int>> q;
meltingTime++;
q.push({0,0});
while(!q.empty()) {
int x = q.front().first;
int y = q.front().second;
q.pop();
visited[x][y] = true;
for(int r=0; r<4; r++) {
int nx = x + dx[r];
int ny = y + dy[r];
if(nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
if(visited[nx][ny]) continue;
if(mat[nx][ny] == 1) {
mat[nx][ny] = 0;
cnt++;
}
else q.push({nx,ny});
visited[nx][ny] = true;
}
}
if(cnt == 0) {
cout<<--meltingTime<<'\n'<<ans;
return true;
}
else {
ans = cnt;
return false;
}
}
int main() {
cin>>N>>M;
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) cin>>mat[i][j];
}
while(true) {
for(int i=0; i<N; i++) {
fill(visited[i], visited[i]+M, false);
}
if(BFS()) break;
}
}
'Algorithm' 카테고리의 다른 글
[BOJ] 불! 4179번 C++ (1) | 2024.02.06 |
---|---|
[BOJ] 숨바꼭질 2 12851번 C++ (1) | 2024.02.02 |
[BOJ] 영화감독 숌 1436번 C++ (0) | 2024.01.30 |
[BOJ] 비밀번호 발음하기 4659번 C++ (1) | 2024.01.30 |
[BOJ] 사과 담기 게임 2828번 C++ (0) | 2024.01.30 |