5 minute read


0. 들어가면서

토마토 문제이다.
시작점이 여러가지인 문제이다.
BFS문제이다.

1. Java

1.1 내가 푼 코드

package bj.ch09_bfs;

import java.util.*;
import java.io.*;

public class BJ_7569_토마토_01 {
    /*
     *
     */
    static int N, M, H;
    static int[][][] box;
    static int[] dh = { -1, 1, 0, 0, 0, 0 };
    // static int[] dn = { 0, 0, 0, 0 - 1, 1 };
    // static int[] dm = { 0, 0, -1, 1, 0, 0 };
    static int[] dn = { 0, 0, -1, 1, 0, 0 };
    static int[] dm = { 0, 0, 0, 0, -1, 1 };
    static Queue<int[]> q = new LinkedList<>();

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        H = Integer.parseInt(st.nextToken());
        box = new int[H][N][M];

        for (int h = 0; h < H; h++) {
            for (int n = 0; n < N; n++) {
                st = new StringTokenizer(br.readLine());
                for (int m = 0; m < M; m++) {
                    int tomato = Integer.parseInt(st.nextToken());
                    box[h][n][m] = tomato;
                    if (tomato == 1) {
                        q.add(new int[] { h, n, m });
                    }
                }
            }
        }

        /////////////////// start ///////////////////
        int result = bfs();
        for (int h = 0; h < H; h++) {
            for (int n = 0; n < N; n++) {
                for (int m = 0; m < M; m++) {
                    if (box[h][n][m] == 0) {
                        System.out.println(-1);
                        return;
                    }
                }
            }
        }
        /////////////////// finish ///////////////////

        System.out.println(result);
    }

    private static int bfs() {
        int day = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] point = q.poll();
                for (int j = 0; j < 6; j++) {
                    int nextH = point[0] + dh[j];
                    int nextN = point[1] + dn[j];
                    int nextM = point[2] + dm[j];
                    if (iNR(nextH, H) || iNR(nextM, M) || iNR(nextN, N)) {
                        continue;
                    }
                    if (box[nextH][nextN][nextM] == 0) {
                        box[nextH][nextN][nextM] = 1;
                        q.offer(new int[] { nextH, nextN, nextM });
                    }
                }
            }
            day++;
        }

        return day - 1;
    }

    private static boolean iNR(int v, int R) { // is not range
        return (v < 0 || v >= R) ? true : false;
    }
}

1.2 chat gpt가 푼 코드

package bj.ch09_bfs;

import java.util.*;

public class BJ_7569_토마토_02_chatgpt {
    static int[][][] boxes;
    static int[] dx = { 0, 0, 0, 0, -1, 1 };
    static int[] dy = { 0, 0, -1, 1, 0, 0 };
    static int[] dz = { -1, 1, 0, 0, 0, 0 };

    static int M, N, H;

    static Queue<int[]> queue = new LinkedList<>();

    static int bfs() {
        int day = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            while (size-- > 0) {
                int[] current = queue.poll();
                for (int i = 0; i < 6; i++) {
                    int nz = current[0] + dz[i];
                    int nx = current[1] + dx[i];
                    int ny = current[2] + dy[i];
                    if (nx < 0 || nx >= N || ny < 0 || ny >= M || nz < 0 || nz >= H) {
                        continue;
                    }
                    if (boxes[nz][nx][ny] == 0) {
                        boxes[nz][nx][ny] = 1;
                        queue.offer(new int[] { nz, nx, ny });
                    }
                }
            }
            day++;
        }
        return day - 1;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        M = sc.nextInt();
        N = sc.nextInt();
        H = sc.nextInt();
        boxes = new int[H][N][M];
        for (int k = 0; k < H; k++) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    boxes[k][i][j] = sc.nextInt();
                    if (boxes[k][i][j] == 1) {
                        queue.offer(new int[] { k, i, j });
                    }
                }
            }
        }

        int result = bfs();
        for (int k = 0; k < H; k++) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (boxes[k][i][j] == 0) {
                        System.out.println(-1);
                        return;
                    }
                }
            }
        }
        System.out.println(result);
    }
}

1.3 바킹독을 참고한 코드

package bj.ch09_bfs;

import java.util.*;
import java.io.*;

public class BJ_7569_토마토_03_BarkingDog {
    /*
     *
     */
    static int N, M, H;
    static int[][][] box;
    static int[][][] dist;
    static int[] dh = { -1, 1, 0, 0, 0, 0 };
    // static int[] dn = { 0, 0, 0, 0 - 1, 1 };
    // static int[] dm = { 0, 0, -1, 1, 0, 0 };
    static int[] dn = { 0, 0, -1, 1, 0, 0 };
    static int[] dm = { 0, 0, 0, 0, -1, 1 };
    static Queue<int[]> q = new LinkedList<>();

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        H = Integer.parseInt(st.nextToken());
        box = new int[H][N][M];
        dist = new int[H][N][M];

        for (int h = 0; h < H; h++) {
            for (int n = 0; n < N; n++) {
                st = new StringTokenizer(br.readLine());
                for (int m = 0; m < M; m++) {
                    int tomato = Integer.parseInt(st.nextToken());
                    box[h][n][m] = tomato;
                    if (tomato == 1) {
                        q.add(new int[] { h, n, m });
                    }
                    if (tomato == 0) {
                        dist[h][n][m] = -1;
                    }
                }
            }
        }

        bfs();
        int result = 0;
        for (int h = 0; h < H; h++) {
            for (int n = 0; n < N; n++) {
                for (int m = 0; m < M; m++) {
                    if (dist[h][n][m] == -1) {
                        System.out.println(-1);
                        return;
                    }
                    result = Math.max(result, dist[h][n][m]);
                }
            }
        }
        System.out.println(result);
    }

    private static void bfs() {
        while (!q.isEmpty()) {
            int[] point = q.poll();
            for (int j = 0; j < 6; j++) {
                int nextH = point[0] + dh[j];
                int nextN = point[1] + dn[j];
                int nextM = point[2] + dm[j];
                if (iNR(nextH, H) || iNR(nextM, M) || iNR(nextN, N)) {
                    continue;
                }
                if (box[nextH][nextN][nextM] == 0) {
                    box[nextH][nextN][nextM] = 1;
                    q.offer(new int[] { nextH, nextN, nextM });
                    dist[nextH][nextN][nextM] = dist[point[0]][point[1]][point[2]] + 1;
                }
            }
        }
    }

    private static boolean iNR(int v, int R) { // is not range
        return (v < 0 || v >= R) ? true : false;
    }
}


1.4 해설

  • 내가 푼 코드와 chatgpt가 푼 코드는 거의 유사하다.
  • 차이점은 주석으로 표시한 부분이다.
  • 변수명만 달라졌을 뿐인데 런타임 에러 여부가 결정 난다.
  • 뭔가 잘 못된 것 같다.
  • 다른 방법으로 풀어보자.
  • 깨닳았다!!!
    • 주석 부분의 출력 부분은 난 err를 사용했었는데, 이게 문제였다.
    • err를 사용하면 런타임 에러가 발생한다.
    • 그래서 out을 사용해야 한다.
      • out은 적절한 타이밍에 flush가 된다.
      • err는 크리티컬한 상황에 쓰이다 보니 flush가 바로 된다.
      • 이렇게 바로 flush가 되면 jvm의 성능에 영향을 준다.
      • 그래서 느려지고 런타임 에러 나는 것이다!!!!!

2. Go

CLOSING

여전히 머리 재활훈련이 필요하다.
err와 out의 flush 타이밍 기억하자!!
그냥 속편하게 out만 쓰자!

Leave a comment