https://www.acmicpc.net/problem/4485
4485번: 녹색 옷 입은 애가 젤다지?
젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다! 젤다의 전설 시리즈의 주
www.acmicpc.net
코드설명
BFS 혹은 다익스트라를 활용하는 문제입니다.
BFS로 푸는것이 더 빠르게 풀 수 있을 것 같아서 BFS로 풀었습니다.
유의해야할점들입니다.
1. 이미 방문했을때 뺏긴 루피보다 크거나 같다면, 해당 공간에 방문하지 않습니다.
아래의 코드에서 처음에 같을때도 방향에 따라 다르게 들어갈 수 있다는 생각으로 < 로 해서 메모리초과가 났었습니다. 생각해보니, BFS 이기에 어디서 들어오든 같은것으로 처리합니다.
if(visited[nx][ny] <= nValue) continue; //이미 최적의 거리로 방문한 적이 있다면, 방문해도 최적의 거리가 나오지 못합니다. // < 냐 <= 냐 에 따라서 메모리초과 <= 로 처리해야합니다.
2. PriorityQueue를 활용하여 뺏긴 루피가 너무 클경우 애초에 Queue에 들어가지 않도록 처리하여 메모리 초과를 벗어날 수 있습니다.
3. "Problem"을 "Probelm" 으로 처리하여 계속해서 오류가 났었습니다.
( BFS가 아닌 우선순위큐를 활용한 다익스트라를 통해서도 해결할 수 있습니다. )
이 문제같은경우 각 루피의 범위를 간선의 가중치라고 생각하고, 간선의 가중치에 음수값이 없으므로 다익스트라로 진행할 수 있습니다. (음수값이 있을경우 벨만포드 알고리즘을 사용해야 합니다.)
코드
우선순위큐를 활용한 BFS 코드입니다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int T, N; public static int[][] arr; public static int answer = Integer.MAX_VALUE; public static int idx = 1; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; public static StringBuilder sb = new StringBuilder(); public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while(true) { answer = Integer.MAX_VALUE; StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); if( N == 0) { break ; } arr = new int[N][N]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); for(int j=0;j<N;j++) { arr[i][j]= Integer.parseInt(st.nextToken()); } } simulate(); } System.out.println(sb); } public static void simulate() { int[][] visited = new int[N][N]; for(int i=0;i<N;i++) { Arrays.fill(visited[i], Integer.MAX_VALUE); } PriorityQueue<Node> pq = new PriorityQueue<>(); // 메모리 초과 문제의 주된 원인 중 하나는 큐가 시뮬레이션의 반복 동안 계속 쌓이면서 메모리를 소비하기에 함수 내부에 선언하여 함수 끝날시에 큐 메모리 삭제되도록 처리 pq.offer(new Node(0, 0, arr[0][0])); visited[0][0] = arr[0][0]; while(!pq.isEmpty()) { Node temp = pq.poll(); int x = temp.x; int y = temp.y; int value = temp.value; // if( x == N-1 && y == N-1) { // answer = Math.min(answer, value); // } for(int dir = 0; dir<4;dir++) { int nx = x + dx[dir]; int ny = y + dy[dir]; if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue; int nValue = value + arr[nx][ny]; if(visited[nx][ny] <= nValue) continue; //이미 최적의 거리로 방문한 적이 있다면, 방문해도 최적의 거리가 나오지 못합니다. // < 냐 <= 냐 에 따라서 메모리초과 <= 로 처리해야합니다. visited[nx][ny] = nValue; pq.offer(new Node(nx, ny, nValue)); } } sb.append("Problem ").append(idx++).append(": ").append(visited[N-1][N-1]).append("\n"); } } class Node implements Comparable<Node>{ int x; int y; int value; public Node(int x, int y, int value) { this.x = x; this.y = y; this.value = value; } @Override public int compareTo(Node other) { if(this.value > other.value) { return 1; }else if(this.value == other.value) { return 0; }else { return -1; } } }
일반 BFS로 푼 코드입니다. (메모리초과 발생)
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int T, N; public static int[][] arr; public static int answer = Integer.MAX_VALUE; public static int idx = 1; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while(true) { StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); if( N == 0) { return ; } arr = new int[N][N]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); for(int j=0;j<N;j++) { arr[i][j]= Integer.parseInt(st.nextToken()); } } answer = Integer.MAX_VALUE; simulate(); } } public static void simulate() { int[][] visited = new int[N][N]; for(int i=0;i<N;i++) { Arrays.fill(visited[i], Integer.MAX_VALUE); } Queue<Node> q = new LinkedList<>(); // 메모리 초과 문제의 주된 원인 중 하나는 큐가 시뮬레이션의 반복 동안 계속 쌓이면서 메모리를 소비하기에 함수 내부에 선언하여 함수 끝날시에 큐 메모리 삭제되도록 처리 q.offer(new Node(0, 0, arr[0][0])); visited[0][0] = arr[0][0]; while(!q.isEmpty()) { Node temp = q.poll(); int x = temp.x; int y = temp.y; int value = temp.value; if( x == N-1 && y == N-1) { answer = Math.min(answer, value); } for(int dir = 0; dir<4;dir++) { int nx = x + dx[dir]; int ny = y + dy[dir]; if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue; int nValue = value + arr[nx][ny]; if(visited[nx][ny] < nValue) continue; //이미 최적의 거리로 방문한 적이 있다면, 방문해도 최적의 거리가 나오지 못합니다. visited[nx][ny] = nValue; q.offer(new Node(nx, ny, nValue)); } } System.out.println("Problem "+idx++ +": "+answer); } } class Node{ int x; int y; int value; public Node(int x, int y, int value) { this.x = x; this.y = y; this.value = value; } }
'알고리즘 > Shortest Path' 카테고리의 다른 글
[백준] 14938 서강그라운드 - 다익스트라(Dijkstra) JAVA (0) | 2023.08.31 |
---|---|
[백준] 1753 최단경로 - 다익스트라(Dijkstra) JAVA (0) | 2023.08.28 |
[백준] 1504 특정한 최단 경로 - 다익스트라(Dijkstra) JAVA (0) | 2023.08.27 |
[백준] 1238 파티 - 다익스트라(Dijkstra) JAVA (0) | 2023.08.12 |
[백준] 5972 택배 배송 - 다익스트라(Dijkstra) JAVA (0) | 2023.08.10 |