ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python][C++] 7569번 토마토
    Algorithm/Baekjoon 2024. 8. 16. 22:58

    문제

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

     

     

    코드

    1. Python

    from collections import deque
    
    # 보드와 방문 여부를 저장하는 배열 초기화
    board = [[[0 for _ in range(100)] for _ in range(100)] for _ in range(100)]
    visited = [[[0 for _ in range(100)] for _ in range(100)] for _ in range(100)]
    
    def bfs(n, m, h):
        # 방향벡터 설정 (6방향)
        dx = [-1, 1, 0, 0, 0, 0]
        dy = [0, 0, -1, 1, 0, 0]
        dz = [0, 0, 0, 0, -1, 1]
    
        q = deque()
    
        # 익은 토마토의 위치를 큐에 삽입하고 방문 처리
        for k in range(h):
            for i in range(n):
                for j in range(m):
                    if board[k][i][j] == 1:
                        q.append((k, i, j))
                        visited[k][i][j] = 1
    
        # BFS 탐색
        while q:
            z, x, y = q.popleft()
    
            for i in range(6):
                nz = z + dz[i]
                nx = x + dx[i]
                ny = y + dy[i]
    
                # 보드 범위를 벗어난 경우 무시
                if nz < 0 or nz >= h or nx < 0 or nx >= n or ny < 0 or ny >= m:
                    continue
    
                # 익지 않은 토마토가 아닌 경우나 이미 방문한 경우 무시
                if board[nz][nx][ny] != 0 or visited[nz][nx][ny] != 0:
                    continue
    
                # 방문처리 및 큐에 삽입
                visited[nz][nx][ny] = visited[z][x][y] + 1
                board[nz][nx][ny] = 1
                q.append((nz, nx, ny))
    
    
    if __name__ == "__main__":
        m, n, h = map(int, input().split())
    
        for k in range(h):
            for i in range(n):
                for j in range(m):
                    board[k][i][j] = int(input())
    
        bfs(n, m, h)
    
        cnt = 0
    
        for k in range(h):
            for i in range(n):
                for j in range(m):
                    cnt = max(cnt, visited[k][i][j])
    
                    if board[k][i][j] == 0:
                        print(-1)
                        exit(0)
    
        print(cnt - 1)

     

    2. C++

    #include <iostream>
    #include <queue>
    #include <tuple>
    using namespace std;
    
    int board[100][100][100];  // 3차원 보드를 나타내는 배열
    int visited[100][100][100] = {};  // 방문 여부와 최단 거리를 저장하는 배열
    
    // BFS 함수 정의
    void bfs(int n, int m, int h) {
        // 6방향(상하좌우, 앞뒤)으로의 이동을 나타내는 배열
        int dx[6] = {-1, 1, 0, 0, 0, 0};
        int dy[6] = {0, 0, -1, 1, 0, 0};
        int dz[6] = {0, 0, 0, 0, -1, 1};
    
        queue<tuple<int, int, int>> q;  // BFS 탐색을 위한 큐, 좌표를 저장 (z, x, y)
    
        // 초기 상태에서 익은 토마토(값이 1인 위치)를 큐에 추가하고 방문 처리
        for (int k = 0; k < h; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (board[k][i][j] == 1) {
                        q.push(make_tuple(k, i, j));
                        visited[k][i][j] = 1;  // 익은 토마토의 위치를 방문 처리
                    }
                }
            }
        }
    
        // BFS 탐색 시작
        while (!q.empty()) {
            int z, x, y;
            tie(z, x, y) = q.front();  // 큐에서 현재 위치를 꺼내옴
            q.pop();
    
            // 6방향으로 인접한 위치를 탐색
            for (int i = 0; i < 6; i++) {
                int nz = z + dz[i];
                int nx = x + dx[i];
                int ny = y + dy[i];
    
                // 인접한 위치가 보드 범위를 벗어나면 무시
                if (nz < 0 || nz >= h || nx < 0 || nx >= n || ny < 0 || ny >= m)
                    continue;
    
                // 인접한 위치가 이미 익었거나 방문된 적이 있으면 무시
                if (board[nz][nx][ny] != 0 || visited[nz][nx][ny] != 0)
                    continue;
    
                // 방문 처리와 함께 큐에 추가
                visited[nz][nx][ny] = visited[z][x][y] + 1;  // 현재 위치에서 +1
                board[nz][nx][ny] = 1;  // 토마토가 익음
                q.push(make_tuple(nz, nx, ny));
            }
        }
    }
    
    int main() {
        int n, m, h;  // n: 행, m: 열, h: 높이
    
        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 >> board[k][i][j];
                }
            }
        }
    
        bfs(n, m, h);  // BFS 탐색 시작
    
        int cnt = 0;  // 최단 시간을 계산하기 위한 변수
    
        // 모든 보드를 탐색하며 최대 방문 시간 계산 및 익지 않은 토마토가 있는지 확인
        for (int k = 0; k < h; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    cnt = max(cnt, visited[k][i][j]);  // 최대 시간을 갱신
    
                    if (board[k][i][j] == 0) {  // 익지 않은 토마토가 있으면
                        cout << -1;  // -1 출력하고 종료
                        return 0;
                    }
                }
            }
        }
    
        cout << cnt - 1;  // 최단 시간 출력 (첫 번째 방문을 1로 초기화했으므로 1을 빼줌)
    
        return 0;
    }

     

     

    풀이 

    1. 3차원 BFS 구현:
      • 일반적인 2차원 BFS와 달리, 이 문제는 3차원이므로 방향을 나타내는 벡터가 6개(위, 아래, 앞, 뒤, 왼쪽, 오른쪽) 필요함
      • BFS를 통해 토마토가 익는데 걸리는 날짜를 계산하며, 모든 익지 않은 토마토가 익을 때까지 반복
    2. 초기 상태 설정:
      • 먼저, 모든 익은 토마토들의 위치를 큐에 넣고, BFS를 시작
    3. 결과 도출:
      • BFS 탐색이 완료된 후, 3차원 배열을 순회하여 익지 않은 토마토(0)가 남아 있는지 확인
      • 남아있다면 -1을 출력하고, 모두 익었다면 그동안 걸린 날짜 중 최대값을 출력

     

     

    https://ehdbs0903.tistory.com/entry/Algorithm-너비-우선-탐색-BFSBreadth-First-Search-알고리즘

     

    [Algorithm] 너비 우선 탐색 / BFS(Breadth-First Search) 알고리즘

    너비 우선 탐색 / BFS (Breadth-First Search) 알고리즘이란?그래프에서 모든 노드를 방문하는 알고리즘 중 하나이다.알고리즘의 기본 아이디어는 가까운 노드부터 먼 노드 순으로 그래프를 탐색하는

    ehdbs0903.tistory.com

     

    'Algorithm > Baekjoon' 카테고리의 다른 글

    [Python][C++]7662번 우선순위 큐  (0) 2024.08.19
    [Python][C++] 7576번 토마토  (0) 2024.08.18
    [Python][C++] 5525번 IOIOI  (0) 2024.08.14
    [Python][C++] 5430번 AC  (0) 2024.08.11
    [Python][C++] 2805번 나무 자르기  (0) 2024.08.10
Designed by Tistory.