[Java] 백준 4485번 녹색 옷 입은 애가 젤다지? with 자바

: ) YOUNG·2022년 5월 13일
3

알고리즘

목록 보기
129/417
post-thumbnail

백준 4485번
https://www.acmicpc.net/problem/4485

문제



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

젤다의 전설 시리즈의 주인공, 링크는 지금 도둑루피만 가득한 N x N 크기의 동굴의 제일 왼쪽 위에 있다. [0][0]번 칸이기도 하다. 왜 이런 곳에 들어왔냐고 묻는다면 밖에서 사람들이 자꾸 "젤다의 전설에 나오는 녹색 애가 젤다지?"라고 물어봤기 때문이다. 링크가 녹색 옷을 입은 주인공이고 젤다는 그냥 잡혀있는 공주인데, 게임 타이틀에 젤다가 나와있다고 자꾸 사람들이 이렇게 착각하니까 정신병에 걸릴 위기에 놓인 것이다.

하여튼 젤다...아니 링크는 이 동굴의 반대편 출구, 제일 오른쪽 아래 칸인 [N-1][N-1]까지 이동해야 한다. 동굴의 각 칸마다 도둑루피가 있는데, 이 칸을 지나면 해당 도둑루피의 크기만큼 소지금을 잃게 된다. 링크는 잃는 금액을 최소로 하여 동굴 건너편까지 이동해야 하며, 한 번에 상하좌우 인접한 곳으로 1칸씩 이동할 수 있다.

링크가 잃을 수밖에 없는 최소 금액은 얼마일까?


생각하기


최소비용을 구하는 다익스트라 알고리즘이지만, 일반 BFS를 접목시키면 쉽게 풀 수 있는 문제였다.

BFS에서 사용하는 Queue를 우선순위큐로 대체한다는 부분만 알아도 절반 이상은 이해하는 문제였다.

동작

		@Override
		public int compareTo(Node o) {
			return size - o.size;
		}

우선순위 큐에서 도둑루피의 크기를 비교할 compareTo 메소드를 오버라이드 해준다.


		while( !que.isEmpty() ) {
	
			Node node = que.poll();

			for(int i=0; i<4; i++) {
				nowX = node.x + dirX[i];
				nowY = node.y + dirY[i];

				if( range_check() && !visit[nowX][nowY] && size[nowX][nowY] > (map[nowX][nowY] + node.size) ) {
					size[nowX][nowY] = map[nowX][nowY] + node.size;
					visit[nowX][nowY] = true;
					que.offer( new Node( nowX, nowY, size[nowX][nowY] ));
				}

			}
		}

	} // End of BFS

(0,0) 부터 시작해서 map 전체를 탐색해서 INF로 되어있는 dist의 값이 비교해서 만약 이동하는 좌표 nowX, nowY의 값 보다 클 경우 size[nowX][nowY] = map[nowX][nowY] + node.size; 새로운 값으로 갱신해준다.





코드


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

public class Main {
	static int dirX[] = {0, 0, -1, 1};
	static int dirY[] = {-1, 1, 0, 0};
	static boolean visit[][];
	static int map[][];
	static int size[][];

	private static final int INF = Integer.MAX_VALUE / 4;
	static int N, nowX, nowY;

	static class Node implements Comparable<Node> {
		int x;
		int y;
		int size;

		// (alt + shift + s) + o
		public Node(int x, int y, int size) {
			this.x = x;
			this.y = y;
			this.size = size;
		}

		@Override
		public int compareTo(Node o) {
			return size - o.size;
		}
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		StringBuilder sb = new StringBuilder(); 
		int count = 1;

		String temp = "";
		while( !(temp = br.readLine()).isEmpty()  ) {
			N = Integer.parseInt(temp);
			if(N == 0) {
				break;
			}

			map = new int[N][N];
			visit = new boolean[N][N];
			size = 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());	
					size[i][j] = INF;
				}
			}

			BFS(0, 0, map[0][0]);
			sb.append("Problem " + count + ": " + size[N-1][N-1]).append('\n');
			count++;
		}

		System.out.println(sb);

	} // End of main

	private static void BFS(int x, int y, int roopy) {
		PriorityQueue<Node> que = new PriorityQueue<>();
		visit[x][y] = true;
		que.offer(new Node(x, y, roopy));

		while( !que.isEmpty() ) {
	
			Node node = que.poll();

			for(int i=0; i<4; i++) {
				nowX = node.x + dirX[i];
				nowY = node.y + dirY[i];

				if( range_check() && !visit[nowX][nowY] && size[nowX][nowY] > (map[nowX][nowY] + node.size) ) {
					size[nowX][nowY] = map[nowX][nowY] + node.size;
					visit[nowX][nowY] = true;
					que.offer( new Node( nowX, nowY, size[nowX][nowY] ));
				}

			}
		}

	} // End of BFS

	private static boolean range_check() {
		return (nowX >= 0 && nowY >= 0 && nowX < N && nowY < N);
	} // End of range_check

} // End of main

0개의 댓글