Algorithm/Problem

녹색 옷 입은 애가 젤다지?(BJ_G4_4485)

당진개발자 2024. 3. 10. 19:57

1. 문제 링크

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

 

4485번: 녹색 옷 입은 애가 젤다지?

젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다! 젤다의 전설 시리즈의 주

www.acmicpc.net


 

2. 나의 코드

메모리: 21020KB 
시간: 264ms 
코드 길이: 2376B
시간 복잡도 : O(N^2logN)
설명
- 다익스트라 알고리즘 사용
- 방문체크, map, result 이렇게 3가지의 2차원 배열을 사용
- bfs를 활용해서 4방 탐색을 하면서 우선순위큐에 넣는다.
- 우선순위큐에서 하나씩 빼면서 전까지의 경로와 자신의 값을 더한 값을 result와 비교하여 작다면 값을 변경한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class BJ_4485 {
    static class Node implements Comparable<Node> {
        int r, c, weight;

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

        @Override
        public int compareTo(Node o) {
            return Integer.compare(this.weight, o.weight);
        }
    }

    static int N;
    static int[][] map, result;
    static boolean[][] visited;
    static int[] dr = {-1, 1, 0, 0};
    static int[] dc = {0, 0, -1, 1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
        int idx = 1;
        while (true) {
            N = Integer.parseInt(br.readLine());
            if (N == 0) break;
            map = new int[N][N];
            result = new int[N][N];
            visited = new boolean[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());
                    result[i][j] = Integer.MAX_VALUE;
                }
            }

            dijkstra();
            System.out.printf("Problem %d: %d\n", idx++, result[N - 1][N - 1]);
        }
    }

    private static void dijkstra() {
        PriorityQueue<Node> pq = new PriorityQueue<>();
        result[0][0] = map[0][0];
        visited[0][0] = true;
        pq.offer(new Node(0, 0, map[0][0]));

        while (!pq.isEmpty()) {
            Node now = pq.poll();

            for (int d = 0; d < 4; d++) {
                int nr = now.r + dr[d];
                int nc = now.c + dc[d];

                if (isValid(nr, nc) && !visited[nr][nc] && now.weight + map[nr][nc] < result[nr][nc]) {
                    visited[nr][nc] = true;
                    result[nr][nc] = now.weight + map[nr][nc];
                    pq.offer(new Node(nr, nc, result[nr][nc]));
                }
            }
        }
    }

    private static boolean isValid(int r, int c) {
        return 0 <= r && r < N && 0 <= c && c < N;
    }
}

 


 

3. 정답 코드

package study0216.src;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Baekjoon4485 {
    static int map[][];
    static boolean visited[][];
    static int minValue[][];
    final static int INF = Integer.MAX_VALUE;
    static int dr[] = {0, 0, 1, -1};
    static int dc[] = {1, -1, 0, 0};

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
        int count = 0;
        while (true) {
            ++count;
            int N = Integer.parseInt(bf.readLine().trim());
            if (N == 0) System.exit(0);

            visited = new boolean[N][N];
            map = new int[N][N];
            minValue = new int[N][N];
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(bf.readLine());
                for (int j = 0; j < N; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                    minValue[i][j] = INF;
                }
            }

            int r = 0, c = 0;
            visited[0][0] = true;
            minValue[0][0] = map[0][0];

            for (int visit = 0; visit < N * N; visit++) {
                // 인접 부분의 거리를 정리해야 함

                for (int d = 0; d < 4; d++) {
                    int nr = r + dr[d];
                    int nc = c + dc[d];
                    if (nr < 0 || nc < 0 || nr >= N || nc >= N || visited[nr][nc]) continue;

                    minValue[nr][nc] = Math.min(minValue[nr][nc], map[nr][nc] + minValue[r][c]);

                }

                //정리가 완료된 후 최소 거리인 미방문 위치로 가야 함
                int nextr = -1;
                int nextc = -1;
                int minLocation = INF;

                for (int i = 0; i < N; i++) {
                    for (int j = 0; j < N; j++) {
                        if (visited[i][j]) continue;
                        if (nextr == -1 || minLocation > minValue[i][j]) {
                            nextr = i;
                            nextc = j;
                            minLocation = minValue[i][j];
                        }
                    }
                }
                if (nextr == -1) break;
                r = nextr;
                c = nextc;
                visited[r][c] = true;
            }
            System.out.println("Problem " + count + ": " + minValue[N - 1][N - 1]);

        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;

public class Main {
    static int N;
    static int[][] map, memo;
    static boolean[][] visited;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int tc = 1;
        while (true) {
            N = Integer.parseInt(br.readLine());
            if (N == 0)
                break;
            map = new int[N][];
            memo = new int[N][N];
            Arrays.stream(memo).forEach(r -> Arrays.fill(r, Integer.MAX_VALUE));
            visited = new boolean[N][N];
            for (int n = 0; n < N; n++)
                map[n] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
            start();
            sb.append("Problem ").append(tc++).append(": ").append(memo[N-1][N-1]).append("\n");
        }
        System.out.println(sb);
    }

    static int[] dr = {0, 1, 0, -1};
    static int[] dc = {1, 0, -1, 0};

    private static void start() {
        PriorityQueue<Pos> pq = new PriorityQueue<>();
        pq.offer(new Pos(0, 0, map[0][0]));

        while (!pq.isEmpty()) {
            Pos p = pq.poll();
            if (p.r == N - 1 && p.c == N - 1)
                break;
            visited[p.r][p.c] = true;
            for (int d = 0; d < 4; d++) {
                int nr = p.r + dr[d];
                int nc = p.c + dc[d];
                if (!isIn(nr, nc) || visited[nr][nc])
                    continue;
                if (p.w + map[nr][nc] < memo[nr][nc]) {
                    memo[nr][nc] = p.w + map[nr][nc];
                    pq.offer(new Pos(nr, nc, memo[nr][nc]));
                }
            }
        }
    }

    private static boolean isIn(int r, int c) {
        return r >= 0 && r < N && c >= 0 && c < N;
    }

    static class Pos implements Comparable<Pos> {
        int r, c, w;

        public Pos(int r, int c, int w) {
            this.r = r;
            this.c = c;
            this.w = w;
        }

        @Override
        public int compareTo(Pos o) {
            return Integer.compare(this.w, o.w);
        }
    }
}

 


 

4. 배운 점

- 2차원 배열을 초기화 하는 방법도 Arrays.fill(minDistance[i], Integer.MAX_VALUE); 사용이 가능하다.
 

- 다익스트라 공부를 자주하자.