문제
https://www.acmicpc.net/problem/2636
2636번: 치즈
아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓
www.acmicpc.net
코드
#include <iostream>
#include <queue>
#include <utility>
using namespace std;
int r,c;
int hour = 0;
int cheese[100][100];
bool isVisited[100][100];
// 동, 남, 서, 북
int dy[4] = {0,1,0,-1};
int dx[4] = {1,0,-1,0};
void initVisited(){
for(int i=0; i<r; i++){
for(int j=0; j<c; j++){
isVisited[i][j]=false;
}
}
}
bool inRange(int y, int x){
return (0<=y&&y<r&&0<=x&&x<c);
}
int bfs(){
isVisited[0][0] = true;
int cnt=0;
queue<pair<int, int>> q;
q.push({0,0});
hour++;
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(inRange(ny, nx) && !isVisited[ny][nx]){
if(cheese[ny][nx]==0) q.push({ny,nx});
else{
cheese[ny][nx]=0;
cnt++;
}
isVisited[ny][nx]=true;
}
}
}
return cnt;
}
int main(){
cin >> r >> c;
for(int i=0; i<r; i++){
for(int j=0; j<c; j++){
cin >> cheese[i][j];
}
}
int preCheeseCnt;
while(true){
initVisited();
int cheeseCnt = bfs();
if(cheeseCnt==0){
cout << hour-1 << '\n' << preCheeseCnt;
break;
}else preCheeseCnt=cheeseCnt;
}
return 0;
}
정리
이 문제에서 중요한 점은 공기와 접촉한 치즈 개수만 세어도 된다는 것이다. 왜나하면 치즈가 다 녹기 전 한 시간 전에 치즈들은 모두 공기와 접촉하기 때문이다. 처음에는 모든 치즈의 개수(공기와 접촉하지 않는 치즈들까지)를 다 세려고 했더니 문제가 잘 풀리지 않았다. 그래서 다른 사람들의 풀이를 보았고 치즈 바깥을 bfs로 돌면서 공기와 치즈가 닿는 부분만을 count해서 문제를 해결했다.
참조
'Beakjoon > DFS, BFS' 카테고리의 다른 글
[백준] 7576번 토마토 (C++) - BFS (0) | 2022.08.30 |
---|---|
[백준] 11403번 경로 찾기 (C++) - DFS, BFS, Floyd Warshall (0) | 2022.02.12 |
[백준] 2667번 단지번호붙이기 (C++) - DFS, BFS (0) | 2022.02.10 |
[백준] 2178번 미로 탐색 (C++) - BFS (0) | 2022.02.08 |
[백준] 2606번 바이러스 (C++) - DFS, BFS (0) | 2022.02.07 |