Algorithm/BOJ

[BOJ] 백준 7569 토마토 c++ 코드 / 풀이

강썬 2023. 11. 5. 17:59

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

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

 

 

 

문제설명

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

 

7576번: 토마토

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

www.acmicpc.net

이 문제의 3차원 버전?

익은 토마토와, 익지않은 토마토가 들어있는 위치, 비어있는 칸의 위치가 주어질 때 

익은 토마토의 위, 아래, 앞, 뒤, 좌, 우에 위치한 익지 않은 토마토는 다음 날 익게 됨

이럴 때 보관된 모든 토마토가 익는 최소 일 수를 출력

 

문제풀이

1. 익은 토마토를 모두 큐에 넣고 BFS 돌리기
2. 입력받을때 아예 1인걸 큐에 넣어버린후에
3. 큐가 빌때까지 BFS실행, 이때 익은 토마토를 0으로 하고 안익은 토마토의 dist을 +1해주면서 재면됨
4. 만약에 BFS 끝났는데 안익은 토마토 있으면 -1 출력 다 익었다면 배열의 max값 출력

 

 

코드설명

익은 토마토의 위치를 큐에 넣고 방문 체크

익지 않은 토마토의 dist 배열 값을 -1로 설정하여 아직 방문하지 않았음을 표시

큐가 빌 때까지 BFS를 실행하며 큐에서 토마토의 위치를 하나씩 꺼내서 해당 토마토의 상하좌우와 위아래 층을 확인

만약 인접한 토마토가 익지 않았다면(dist 값이 -1), 현재 토마토의 dist 값에 1을 더하여 인접한 토마토의 dist 값을 갱신

이 값은 시작점으로부터의 거리(일수)

각 방향을 확인할 때, 상자의 범위를 벗어나지 않는지, 이미 방문했는지(즉, dist 값이 0 이상) 확인

BFS 실행이 끝나면, dist 배열을 검사하여 모든 토마토가 익었는지 확인

만약 익지 않은 토마토가 있다면(즉, dist 값이 -1인 칸이 있다면) -1을 출력

모든 토마토가 익었다면, dist 배열 중 최댓값을 찾아 출력

 

코드

#include <bits/stdc++.h>
#define PRESET ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int arr[101][101][101];
int dist[101][101][101];
int main(){
    PRESET;

    /*
    1. 익은 토마토를 모두 큐에 넣고 BFS 돌리기
    2. 입력받을때 아예 1인걸 큐에 넣어버린후에
    3. 큐가 빌때까지 BFS실행, 이때 익은 토마토를 0으로 하고 안익은 토마토의 dist을 +1해주면서 재면됨
    4. 만약에 BFS 끝났는데 안익은 토마토 있으면 -1 출력 다 익었다면 배열의 max값 출력
    
    */

    queue<tuple<int, int, int>> q;
    int N, M, H;

    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1}; //하, 우, 상, 좌1
    int dz[4] = {-1, 1};
    int max_cnt = 0, cnt = 0;// max size

    cin >> M >> N >> H;
    for(int k = 0; k < H; k++){
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++){
                cin >> arr[k][i][j];
                if(arr[k][i][j] == 1) q.push({k,i,j});
                if(arr[k][i][j] == 0) dist[k][i][j] = -1;
            }
        }
    }
    while(!q.empty()){
        auto cur = q.front(); q.pop();
        for(int i = 0; i < 4; i++){         
            int nx = get<1>(cur) + dx[i];
            int ny = get<2>(cur) + dy[i];

            if(nx < 0 || nx >= N || ny < 0 || ny >= M ) continue;
            if(dist[get<0>(cur)][nx][ny] >= 0) continue;

            dist[get<0>(cur)][nx][ny] = dist[get<0>(cur)][get<1>(cur)][get<2>(cur)] + 1;
            q.push({get<0>(cur),nx,ny});
        }
        for(int i = 0; i < 2; i++){
            int nz = get<0>(cur) + dz[i];
            
            if(nz < 0 || nz >= H) continue;
            if(dist[nz][get<1>(cur)][get<2>(cur)] >= 0) continue;

            dist[nz][get<1>(cur)][get<2>(cur)] = dist[get<0>(cur)][get<1>(cur)][get<2>(cur)] + 1;
            q.push({nz, get<1>(cur), get<2>(cur)});
        }
    }

for(int k = 0; k < H; k++){
    for(int i = 0; i < N; i++){
        for(int j = 0; j < M; j++){
            if(dist[k][i][j] == -1) {
                cout << -1;
                return 0;
            }
            else{
                max_cnt = max(max_cnt, dist[k][i][j]);
            }
        }
    }
}
    cout << max_cnt;
    
}