안녕하세요 여러분~!~!~!~!~~~!!
프루니입니다 ^_______~
오늘 풀어볼 문제는 백준 7576번 토마토 문제입니다.
언어는 C++입니다!
BFS로 구현했습니다!
첨에 DFS로 풀어보려다가 뭐지...? 싶어서 다시 생각하다가 BFS로 풀어야한다는 것을 뒤늦게 깨달았어용 ㅠㅠ
시간을 매우 많이 낭비한 것은 비밀.......ㅎㅎ
자 그럼! BFS로 제대로 문제 마스터하러 가봅시다!!!!!!!!

문제
철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자 모양 상자의 칸에 하나씩 넣어서 창고에 보관한다.

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토의 인접한 곳은 왼쪽, 오른쪽, 앞, 뒤 네 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지, 그 최소 일수를 알고 싶어 한다.
토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 칸에는 토마토가 들어있지 않을 수도 있다.
입력
첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다.
토마토가 하나 이상 있는 경우만 입력으로 주어진다.
출력
여러분은 토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.
프루니의 풀이
사용언어 : C++
사용 알고리즘: BFS
문제 해석
익은 토마토의 상, 하, 좌, 우에 위치한 안 익은 토마토들이 익을 수 있을 때 전체 토마토가 모두 익을때까지 걸리는 시간을 구하는 문제입니다.
익은 토마토가 들어있는 칸은 1로 표현되고 익지 않은 토마토가 들어있는 칸은 0, 토마토가 없는 칸은 -1로 표시됩니다.
그래서 우리가 해야하는 것은 바로바로!
익은 토마토가 들어있는 칸들을 모두 큐에 넣고 바로 BFS를 때려주면 됩니다!!
BFS를 쓰는 이유는 인접한 토마토들을 바로 익혀버리기 위해서에요!!
DFS를 쓰면 인접한 토마토 중에 하나로 이동하고 또 거기서 인접한 토마토 중에 하나의 토마토로 이동해버려서 동일한 토마토에 인접한 토마토들이 동시에 익지 않아요!!
어떻게 아냐구요...?? 저도 알고 싶지 않았어요.............실수로 처음에 DFS로 풀다가 말도 안되는 답이 출력되길래 디버그해보다가 알았답니다... ㅎㅎ

그림이 진짜 찐따같은 것을 알지만... 저 그림으로 설명을 하겠습니다. (다음부턴 그림 툴을 탐색해서 예쁘게 그려올게요...!!)
각 칸에 검정색으로 쓰여있는 숫자가 입력된 숫자이구요! 검정색 외의 숫자로 써져있는 숫자들은 해당칸의 토마토가 익는데 필요한 시간이에요!! 같은 시간을 같은 색깔로 표현해놨어요!
코드를 작성할 단계를 간단하게 정리했어요!
0단계 : BFS를 돌릴 큐를 하나 만듭니다.
1단계 : 입력받은 배열에서 익은 토마토(1로 표시된 칸)를 모두 찾아서 만들어둔 큐에 넣어줍니다.
2단계 : 큐의 맨처음 요소부터 검사하면서 현재 칸의 인접한 칸 중 0인 칸들의 숫자를 (현재 칸 숫자 +1)로 변경한 후 변경한 칸들을 모두 큐에 Push해줍니다.
3단계 : 큐의 요소가 모두 없어질때까지 반복합니다.
4단계 : 토마토 칸 전체를 검사하며 가장 큰 숫자를 Result로 설정합니다.
5단계 : Result - 1을 출력합니다. (1을 빼는 이유는 시작점이 1이라서 이것을 1을 빼줘야합니다!)
구현 코드
이제 구현한 코드를 보여드릴게요!!
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <memory.h>
using namespace std;
int N, M;
int fruit[1001][1001];
bool visited[1001][1001];
int rl[4] = {1, 0, 0, -1};
int ud[4] = {0, 1, -1, 0};
queue<pair<int, int>> q;
void BFS()
{
while (!q.empty())
{
pair<int, int> front = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int newCol = front.first + ud[i];
int newRow = front.second + rl[i];
if (newCol < 1 || newCol > M || newRow < 1 || newRow > N)
{
continue;
}
if (fruit[newCol][newRow] == 0 && !visited[newCol][newRow])
{
visited[newCol][newRow] = true;
q.push(make_pair(newCol, newRow));
fruit[newCol][newRow] = fruit[front.first][front.second] + 1;
}
}
}
}
int main()
{
cin.tie(0);
cin.sync_with_stdio(0);
cin >> N >> M;
int notRipened = 0;
for (int i = 1; i <= M; ++i)
{
for (int j = 1; j <= N; ++j)
{
cin >> fruit[i][j];
if (fruit[i][j] == 1)
{
q.push(make_pair(i, j));
}
}
}
BFS();
int res = 0;
for (int i = 1; i <= M; ++i)
{
for (int j = 1; j <= N; ++j)
{
if (fruit[i][j] == 0)
{
cout << "-1\n";
return 0;
}
res = max(res, fruit[i][j]);
}
}
cout << --res << '\n';
return 0;
}
여러분 고생많으셨습니다~~~
도움이 되셨다면 공감버튼 한번씩 눌러주시면 넘 감사하겠습니다!!
질문은 댓글로 달아주시면 최대한 빠르게 달려가서 답변드리겠습니다!
알고리즘 마스터를 향해!!!! 열심히 달려가봅시다~~~~!!
그럼 저는 또 다음 문제를 가지고 올게요~~
안녕~~~~~~~~

'코딩테스트 > 백준' 카테고리의 다른 글
| 백준 13549 C++ 숨바꼭질 3 (BFS) (0) | 2024.04.14 |
|---|---|
| 백준 14226 이모티콘 C++ 풀이 (BFS) (0) | 2024.04.14 |
| 백준 15563 N과M (9) C++ 풀이 (무조건 이해시켜드림) (0) | 2024.03.17 |
| 백준 15654 N과M (5) C++ 풀이 (무조건 이해시켜드림) (3) | 2024.03.17 |
| 백준 15650 N과M (2) C++ 풀이 (무조건 이해시켜드림) (0) | 2024.03.17 |