CodingTest/백준
[백준] BOJ 4485 녹색 옷 입은 애가 젤다지? (골드 4)
브디크리
2024. 4. 10. 17:08
문제
https://www.acmicpc.net/problem/4485
4485번: 녹색 옷 입은 애가 젤다지?
젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다! 젤다의 전설 시리즈의 주
www.acmicpc.net
해설
풀이 1. BFS
- 2차원 배열에 해당 위치를 방문했을 때 비용을 누적할 수 있도록 한다.
- 일반적으로 BFS를 통해 탐색하면, 이미 방문한 곳을 다시 방문할 수 없기 때문에,
이미 방문한 경우에 더 적은 비용으로 해당 위치를 방문한 경우 해당 위치의 비용을 변경해주고 다시 큐에 넣어준다.
풀이 2. BFS + 우선순위 큐
- 풀이 1에 우선순위 큐 적용
- 가장 비용이 작은 것을 먼저 탐색해서 목적지에 도달하면
이 후 도착하는 값들은 모두 해당 비용보다 크므로 모두 탐색하기 전에 종료할 수 있다.
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
int cnt = 1;
while (true) {
int N = Integer.parseInt(br.readLine());
if(N == 0){
break;
}
int[][] map = new int[N][N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
sb.append("Problem ").append(cnt++).append(": ")
.append(bfs(N, map)).append("\n");
}
bw.write(sb.toString());
bw.flush();
bw.close();
}
//풀이 2 (1번 풀고 다른 사람 풀이 보고 생각나서 했음 첨부터 내 머리속에서 나온거 아님 ㅠㅠ)
private static long bfs_priority(int N, int[][] map) {
class Point implements Comparable<Point>{
int row;
int col;
int cost;
public Point(int row, int col, int cost) {
this.row = row;
this.col = col;
this.cost = cost;
}
@Override
public int compareTo(Point p) {
return cost - p.cost; //작은게 우선순위 높게
}
}
int[] dy = {0, -1, 0, 1};
int[] dx = {-1, 0, 1, 0};
boolean[][] isVisit = new boolean[N][N];
PriorityQueue<Point> queue = new PriorityQueue<>();
queue.add(new Point(0,0,map[0][0]));
isVisit[0][0] = true;
while (!queue.isEmpty()){
Point point = queue.poll();
int row = point.row;
int col = point.col;
int cost = point.cost;
for (int i = 0; i < 4; i++) {
int y = row + dy[i];
int x = col + dx[i];
if(y == N - 1 && x == N - 1){
return cost + map[y][x];
}
if ((y < 0 || y >= N || x < 0 || x >= N) || isVisit[y][x]) {
continue;
}
isVisit[y][x] = true;
queue.offer(new Point(y, x, map[y][x] + cost));
}
}
return 0;
}
//풀이 1
private static long bfs(int N, int[][] map) {
class Point{
int row;
int col;
int cost;
public Point(int row, int col, int cost) {
this.row = row;
this.col = col;
this.cost = cost;
}
}
int[] dy = {0, -1, 0, 1};
int[] dx = {-1, 0, 1, 0};
boolean[][] isVisit = new boolean[N][N];
int[][] costs = new int[N][N];
Queue<Point> queue = new LinkedList<>();
queue.add(new Point(0,0,map[0][0]));
isVisit[0][0] = true;
costs[0][0] = map[0][0];
while (!queue.isEmpty()){
Point point = queue.poll();
int row = point.row;
int col = point.col;
int cost = point.cost;
for (int i = 0; i < 4; i++) {
int y = row + dy[i];
int x = col + dx[i];
if(y < 0 || y >= N || x < 0 || x >= N){
continue;
}
//아직 방문하지 않았다면 해당 좌표 + 이전 비용 + 현재 비용
if(!isVisit[y][x]){
queue.add(new Point(y, x, cost + map[y][x]));
costs[y][x] = cost + map[y][x];
isVisit[y][x] = true;
}
//이미 방문했지만 비용감소가 가능한 경우
if(isVisit[y][x] && costs[y][x] > (cost + map[y][x])){
queue.add(new Point(y, x, cost + map[y][x]));
costs[y][x] = cost + map[y][x];
}
}
}
return costs[N-1][N-1];
}
}
결론
이때는 Priority Queue를 사용하는 것이 익숙하지 않았는데 지나고 나서 보니 많이 성장한 것 같아서 뿌듯하다!