영벨롭 개발 일지

[백준 BOJ][C++]7576번 토마토 풀이: BFS/DFS 본문

알고리즘 문제 풀이/BOJ

[백준 BOJ][C++]7576번 토마토 풀이: BFS/DFS

영벨롭 2022. 2. 28. 15:25

https://www.acmicpc.net/problem/7576

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토

www.acmicpc.net

 

 이 문제는 BFS를 사용하여 해결할 수 있습니다. 

 

 M*N 크기의 토마토 농장에서 모든 토마토가 익을 때까지 걸리는 최소일은 익은 토마토로부터 시작해 그래프 탐색이 완료 되었을 때의 리프 노드 중, 최대 부모 노드의 수가 됩니다. 

 

 예시로 다음과 같은 3*3 토마토 농장을 들겠습니다. 

0  0  0

 0  0  0 

0  0  1

index: x(col), y(row) 0 1 2
0 0 0 0
1 0 0 0
2 0 0 1

 

 이제 이 토마토 농장의 토마토 정보를 가지고 BFS를 하면 방문 순서는 다음과 같습니다. 

 

 

익은 토마토의 위치인 (2, 2)에서 시작해 BFS를 하여 완료된 모습입니다. 

 

이때 각 리프 노드인 (1, 0), (0, 0), (0, 2)의 부모 노드 수는 각각 3개, 4개, 2개가 됩니다. 

 

 최댓값인 4가 모든 토마토가 익을 때까지 걸리는 최소일수가 됩니다. 

 

 

typedef struct node {
	int x, y;  //위치
	int parent_num; //부모 노드 개수
}node;

queue<node> tomato;

 queue에 들어가는 자료구조로는 토마토의 위치 x, y와 부모 노드의 개수 parent_num이 사용됩니다. 

 

 토마토 정보를 입력받을 때 1이라면 queue<node> tomato에 push해줍니다. 이때 parent_num의 값은 0이 됩니다. 

 

 queue에 정보를 기록했으면 이제 기존 bfs 방식과 동일하게 진행하면 됩니다. 

 

 이때 인접한 익지 않은 토마토 노드를 queue에 push할 때 해당 노드의 parent_num은 부모 노드의 parent_num+1이 되겠지요!

 

bool all_visit() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (map[i][j] == 0 && !visit[i][j])
				return false;
		}
	}
	return true;
}

 bfs()가 완료되면 all_visit() 함수를 호출하여 익지 않은 토마토가 모두 익었는지 체크해야 합니다. 이때 false를 return 받게 되면 결과는 -1로 해주어야겠지요!

 

 

전체 코드입니다. 

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstdlib>

using namespace std;

int m, n;
int map[1001][1001];
bool visit[1001][1001] = { false, };
int day = 0;

int dx[4] = { 1, 0, 0, -1 };
int dy[4] = { 0, 1, -1, 0 };

typedef struct node {
	int x, y;
	int parent_num;
}node;

queue<node> tomato;

bool all_visit() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (map[i][j] == 0 && !visit[i][j])
				return false;
		}
	}
	return true;
}

void bfs() {

	node curr;

	while (!tomato.empty()) {
		curr = tomato.front();
		tomato.pop();

		for (int i = 0; i < 4; i++) {
			int tx = curr.x + dx[i];
			int ty = curr.y + dy[i];

			if (tx < 0 || tx >= m || ty < 0 || ty >= n)
				continue;
			if (visit[ty][tx] || map[ty][tx] != 0)
				continue;

			visit[ty][tx] = true;

			node child;
			child.x = tx;
			child.y = ty;
			child.parent_num = curr.parent_num + 1;

			tomato.push(child);
		}

		day = max(day, curr.parent_num);
	}

}

int main(void) {

	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> m >> n;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];

			if (map[i][j] == 1) {
				tomato.push({ j, i, 0 });
			}
		}
	}

	bfs();

	if (!all_visit())
		day = -1;

	cout << day;

	return 0;
}
반응형