Study/Problem Solving

[백준 / Java] 4485번: 녹색 옷 입은 애가 젤다지? (골드4)

Pearlii 2023. 10. 5. 17:28

문제 풀이 날짜: 2023.10.05
포스트 작성일: 2023.10.05

 

* 학습 목적으로 작성하는 글입니다. 풀이가 정석적이지 못할 수도 있습니다.

 

문제 출처

백준 온라인 저지 4485번: 녹색 옷 입은 애가 젤다지? (골드4)

 

키워드

다익스트라 (BFS + DP)

 

풀이 접근법

  • 그래프의 시작점에서 끝까지 최소 비용으로 이동해야 한다. → 다익스트라 사용
    • 단순히 BFS로만 DP값을 갱신시키면 원하는 답이 잘 나오지 않는다. 따라서 우선순위 큐를 사용하는 다익스트라를 이용할 필요가 있다.
  • 주어진 인접 행렬은 상하좌우로 노드가 연결된 그래프로 볼 수 있다. 따라서 사방탐색을 하며 이동 가중치의 합을 갱신시킨다.
  • 이 때, 가중치의 합을 저장하는 DP 배열의 값이 이전보다 더욱 작은 값으로 갱신되었다면 해당 정점을 경유하는 다른 경로 또한 더욱 짧은 길이로 갱신될 수 있다.
  • 따라서 해당 정점의 방문 여부와 무관하게 DP값이 갱신되었다면 재탐색(Queue에 add())한다.
  • 도착지점에 다다를 때까지 위 과정을 반복한다.

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {

	private static int N;

	private static int[][] matrix;
	private static int[][] DP;

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

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int tc = 1;
		StringBuilder sb = new StringBuilder();
		while ((N = Integer.parseInt(br.readLine())) != 0) {
			matrix = new int[N][N];
			DP = new int[N][N];

			StringTokenizer st;
			for (int i = 0; i < N; i++) {
				st = new StringTokenizer(br.readLine(), " ");
				for (int j = 0; j < N; j++) {
					matrix[i][j] = Integer.parseInt(st.nextToken());
					DP[i][j] = Integer.MAX_VALUE;
				}
			}

			dijkstra(0, 0);
			
			sb.append("Problem ").append(tc++).append(": ")
			.append(DP[N - 1][N - 1]).append("\n");
		}

		System.out.print(sb);
	}

	private static void dijkstra(int startR, int startC) {
		PriorityQueue<Node> pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o1.dist, o2.dist));

		DP[startR][startC] = matrix[startR][startC];
		pq.add(new Node(startR, startC, DP[startR][startC]));

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

			if (n.row == N - 1 && n.col == N - 1) {
				return;
			}

			int nr = 0;
			int nc = 0;
			for (int i = 0; i < dr.length; i++) {
				nr = n.row + dr[i];
				nc = n.col + dc[i];

				if (!isValid(nr, nc)) {
					continue;
				}

				//DP값이 갱신됐다면 재탐색 해야하므로 별도의 visit 처리는 하지 않는다.
				if (DP[n.row][n.col] + matrix[nr][nc] < DP[nr][nc]) {
					DP[nr][nc] = DP[n.row][n.col] + matrix[nr][nc];
					pq.add(new Node(nr, nc, DP[nr][nc]));
				}
			}
		}

		return;
	}

	private static boolean isValid(int nr, int nc) {
		return (nr > -1 && nc > -1 && nr < N && nc < N);
	}
}

class Node {
	int row;
	int col;
	int dist;

	public Node(int row, int col, int dist) {
		this.row = row;
		this.col = col;
		this.dist = dist;
	}
}

 

 

git 링크

(git 링크 첨부)