백준 4485 JAVA : 녹색 옷 입은 애가 젤다지?

문제

백준 문제 링크 : https://www.acmicpc.net/problem/4485

풀이전략

  1. 처음에는 전형적인 BFS문제라고 생각했다. 하지만 그냥 Queue와 dp 배열로 하면, 완전한 최적화를 할 수 없다. (필자는 메모리초과 문제가 계속 발생하였다.) 따라서 분명 NXN 격자 문제를 해결하는 거지만 마치 다익스트라 알고리즘을 해결하는 것처럼 문제를 접근하면 최적화 할 수 있다.
  2. 다익스트라에 아직 완전히 익숙하지 않은 것 같다. 부등호를 실수하여 중복된 노드가 실행되도록 만들어 메모리 초과를 야기했다. 항상 다익스트라를 할 때 중복이 되는지 조건을 잘 확인하자.

코드

package backjoon.P4485;

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

public class Main {

    static class Node {
        public int r, c, val;

        public Node(int r, int c, int val) {
            this.r = r;
            this.c = c;
            this.val = val;
        }
    }

    static int[] dy = {-1, 0, 1, 0};
    static int[] dx = {0, 1, 0, -1};
    static int[][] dp;
    static int[][] map;

    public static int dijkstra(int N) {
        PriorityQueue<Node> q = new PriorityQueue<>((n1, n2) -> n1.val - n2.val);
        dp[0][0] = map[0][0];
        q.add(new Node(0, 0, map[0][0]));
        while (!q.isEmpty()) {
            Node cur = q.poll();
            for (int i = 0; i < 4; i++) {
                int rr = cur.r + dy[i];
                int cc = cur.c + dx[i];

                if (rr < 0 || rr >= N || cc < 0 || cc >= N)
                    continue;
                int nextVal = cur.val + map[rr][cc];
                // 이거 한줄 떄매 계속 문제남 .... <= 로 처리를 해주면 되는데
                // 나는 < 로 처리함 -> 중복되는 것을 구했기 때문에 메모리 초과
                if (dp[rr][cc] <= nextVal)
                    continue;
                dp[rr][cc] = nextVal;
                q.add(new Node(rr, cc, nextVal));
            }
        }
        return dp[N - 1][N - 1];
    }

    public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("src/backjoon/input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder("");
        int p = 0;
        while (true) {
            int N = Integer.parseInt(br.readLine());
            p++;
            if (N == 0)
                break;
            dp = new int[N][N];
            map = new int[N][N];
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < N; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                    dp[i][j] = Integer.MAX_VALUE;
                }
            }

            System.out.println("Problem " + p + ": " + dijkstra(N));
        }
        bw.flush();
    }
}

회고

  • 격자 문제를 풀 때 마치 다익스트라로 문제를 해결하듯이 문제를 접근 할 수 있다. (조금 더 최적화 된 결과를 Priority Queue를 통해 얻을 수 있다.) 따라서 항상 열린 마음으로 문제를 접근해야겠다.
  • 다익스트라에서 중복조건이 발생하지 않도록 항상 주의하자.

Written by@Gomster
항상 노력하고 나아가는 백엔드 개발자가 되고 싶은 대학생입니다.

GitHub