Home BOJ. Tomato (7569)
Post
Cancel

BOJ. Tomato (7569)

Problem link

Each tomato box is a three-dimensional grid. A ripe tomato ripens its unripe neighbors in the six axis-aligned directions, and all changes happen simultaneously one day at a time. The task is to find the number of days until no unripe tomatoes remain, or report -1 if some can never ripen.

Use multi-source breadth-first search: enqueue every initially ripe tomato before searching. Store each queued cell as one flattened integer index in a primitive int[] whose capacity is the total number of cells. A cell is enqueued only when it changes from unripe to ripe, so it enters the queue at most once.

The grid value doubles as the day label: initial ripe cells are 1, and a newly ripened cell gets its predecessor’s value plus one. Thus each BFS layer represents one simultaneous day. Count unripe cells while reading input; decrement the count as they ripen. If it starts at zero, the answer is 0. If it is still positive after the queue is exhausted, return -1; otherwise the largest grid value minus one is the number of elapsed days.

The input reader parses whitespace-separated integers without relying on line boundaries.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import java.io.BufferedInputStream;
import java.io.IOException;

public class Main {
    private static int m, n, h;
    private static final int[] DZ = {1, -1, 0, 0, 0, 0};
    private static final int[] DY = {0, 0, 1, -1, 0, 0};
    private static final int[] DX = {0, 0, 0, 0, 1, -1};

    public static void main(String[] args) throws IOException {
        FastScanner in = new FastScanner();
        m = in.nextInt();
        n = in.nextInt();
        h = in.nextInt();

        int volume = m * n * h;
        int[][][] box = new int[h][n][m];
        int[] queue = new int[volume];
        int tail = 0;
        int unripe = 0;

        for (int z = 0; z < h; z++) {
            for (int y = 0; y < n; y++) {
                for (int x = 0; x < m; x++) {
                    int value = in.nextInt();
                    box[z][y][x] = value;
                    if (value == 1) {
                        queue[tail++] = (z * n + y) * m + x;
                    } else if (value == 0) {
                        unripe++;
                    }
                }
            }
        }

        System.out.println(ripeningDays(box, queue, tail, unripe));
    }

    private static int ripeningDays(int[][][] box, int[] queue, int tail, int unripe) {
        if (unripe == 0) {
            return 0;
        }

        int maxDay = 1;
        for (int head = 0; head < tail; head++) {
            int index = queue[head];
            int z = index / (n * m);
            int remainder = index % (n * m);
            int y = remainder / m;
            int x = remainder % m;
            int nextDay = box[z][y][x] + 1;

            for (int direction = 0; direction < 6; direction++) {
                int nz = z + DZ[direction];
                int ny = y + DY[direction];
                int nx = x + DX[direction];
                if (nz < 0 || nz >= h || ny < 0 || ny >= n || nx < 0 || nx >= m
                        || box[nz][ny][nx] != 0) {
                    continue;
                }

                box[nz][ny][nx] = nextDay;
                maxDay = nextDay;
                unripe--;
                queue[tail++] = (nz * n + ny) * m + nx;
            }
        }

        return unripe == 0 ? maxDay - 1 : -1;
    }

    private static final class FastScanner {
        private final BufferedInputStream in = new BufferedInputStream(System.in);
        private final byte[] buffer = new byte[1 << 16];
        private int pointer, length;

        int nextInt() throws IOException {
            int c;
            do {
                c = read();
            } while (c <= ' ' && c != -1);

            int value = 0;
            while (c > ' ') {
                value = value * 10 + c - '0';
                c = read();
            }
            return value;
        }

        private int read() throws IOException {
            if (pointer == length) {
                length = in.read(buffer);
                pointer = 0;
                if (length == -1) {
                    return -1;
                }
            }
            return buffer[pointer++];
        }
    }
}

Every cell is inserted at most once and checks at most six neighbors, so the running time is O(MNH). The grid and primitive queue each use O(MNH) storage.

This post is licensed under CC BY 4.0 by the author.

Buy me a coffee