🌞Algorithm/πŸ”₯Baekjoon

[Baekjoon] 19238_μŠ€νƒ€νŠΈ νƒμ‹œ

λΏŒμ•Ό._. 2024. 2. 5. 17:22

Gold II

문제(좜처: https://www.acmicpc.net/problem/19238)

< μŠ€νƒ€νŠΈ νƒμ‹œ >

 

문제 풀이 

 

ν˜„μž¬ μœ„μΉ˜μ—μ„œ λͺ¨λ“  μœ„μΉ˜λ₯Ό νƒμƒ‰ν•˜μ—¬ κ°€μž₯ κ°€κΉŒμ΄ μžˆλŠ” μ†λ‹˜μ„ μ°ΎλŠ”λ‹€. μ†λ‹˜ μœ„μΉ˜λ‘œ 이동 ν›„ μ†λ‹˜μ˜ λͺ©μ μ§€κΉŒμ§€ μ΄λ™ν•œλ‹€. 이 과정을 λͺ¨λ“  μ†λ‹˜μ„ μ΄λ™μ‹œν‚¬ λ•ŒκΉŒμ§€ λ°˜λ³΅ν•œλ‹€.

 

이 λ¬Έμ œμ—μ„œ κ³ λ €ν•΄μ•Ό ν•  것은 μ΅œλ‹¨ 거리가 같은 μ†λ‹˜μ΄ μžˆλ‹€λ©΄ ν–‰ λ²ˆν˜Έκ°€ μž‘κ³ , μ—΄ λ²ˆν˜Έκ°€ μž‘μ€ μ†λ‹˜μ„ 택해야 ν•˜λŠ” 것이닀. 

 

 my solution (Java)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;

public class _19238_ { // μŠ€νƒ€νŠΈ νƒμ‹œ
	static int arr[][], n;
	static boolean visited[][];
	static int dx[] = { -1, 0, 0, 1 }; // μƒμ’Œμš°ν•˜
	static int dy[] = { 0, -1, 1, 0 };

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());

		n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int fuel = Integer.parseInt(st.nextToken());

		arr = new int[n + 1][n + 1];
		visited = new boolean[n + 1][n + 1];

		for (int i = 1; i <= n; i++) {
			st = new StringTokenizer(bf.readLine());
			for (int j = 1; j <= n; j++) {
				arr[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		st = new StringTokenizer(bf.readLine());
		int x = Integer.parseInt(st.nextToken());
		int y = Integer.parseInt(st.nextToken());

		int idx = 2;
		HashMap<Integer, int[]> map = new HashMap<>();

		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(bf.readLine());
			int startX = Integer.parseInt(st.nextToken());
			int startY = Integer.parseInt(st.nextToken());
			int endX = Integer.parseInt(st.nextToken());
			int endY = Integer.parseInt(st.nextToken());

			arr[startX][startY] = idx;
			map.put(idx++, new int[] { endX, endY });
		}

		while (fuel > 0) {
			init();
			int info[] = findCustomer(x, y);

			if (info[0] == -1 && info[1] == -1) {
				break;
			}

			arr[info[0]][info[1]] = 0;
			fuel -= info[3];
			if (fuel <= 0) {
				break;
			}

			init();
			info = taxi(info[0], info[1], map.get(info[2]));

			if (info[0] == -1 && info[1] == -1) {
				break;
			}

			fuel -= info[2];
			if (fuel < 0) {
				break;
			}
			fuel += (info[2] * 2);
			m -= 1;
			x = info[0];
			y = info[1];

			if (m == 0) {
				break;
			}

		}

		if (m > 0 || fuel <= 0) { // λͺ¨λ“  μ†λ‹˜μ„ μ΄λ™μ‹œν‚¬ 수 μ—†κ±°λ‚˜ 이동 도쀑에 μ—°λ£Œκ°€ λ°”λ‹₯λ‚œ 경우
			System.out.println(-1);
		} else { // λͺ¨λ“  μ†λ‹˜μ„ μ΄λ™μ‹œν‚€κ³  μ—°λ£Œλ₯Ό μΆ©μ „ν–ˆμ„ λ•Œ 남은 μ—°λ£Œμ˜ μ–‘
			System.out.println(fuel);
		}

	}

	// λ°©λ¬Έ λ°°μ—΄ μ΄ˆκΈ°ν™”
	private static void init() {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				visited[i][j] = false;
			}
		}

	}

	// ν˜„μž¬ μœ„μΉ˜μ—μ„œ κ°€μž₯ κ°€κΉŒμš΄ μ†λ‹˜ μ°ΎκΈ°
	private static int[] findCustomer(int x, int y) {
		if (arr[x][y] > 1) {
			return new int[] { x, y, arr[x][y], 0 };
		}

		Queue<int[]> queue = new LinkedList<>();
		PriorityQueue<int[]> pri = new PriorityQueue<>(new Comparator<int[]>() {

			@Override
			public int compare(int[] o1, int[] o2) {
				if (o1[3] == o2[3]) {
					if (o1[0] == o2[0]) {
						return o1[1] - o2[1];
					}
					return o1[0] - o2[0];
				}
				return o1[3] - o2[3];
			}
		});
		queue.add(new int[] { x, y, 0 });
		visited[x][y] = true;

		while (!queue.isEmpty()) {
			int info[] = queue.poll();
			for (int i = 0; i < 4; i++) {
				int a = info[0] + dx[i];
				int b = info[1] + dy[i];
				if (a > 0 && a <= n && b > 0 && b <= n && arr[a][b] != 1 && !visited[a][b]) {
					visited[a][b] = true;
					if (arr[a][b] > 1) {
						if (pri.size() == 0 || pri.peek()[3] >= info[2] + 1) {
							pri.add(new int[] { a, b, arr[a][b], info[2] + 1 });
						}
					}
					queue.add(new int[] { a, b, info[2] + 1 });
				}
			}
		}

		if (pri.isEmpty()) {
			return new int[] { -1, -1, -1, -1 };
		} else {
			return pri.poll();
		}
	}

	// μ†λ‹˜ μΆœλ°œμ§€μ—μ„œ λͺ©μ μ§€κΉŒμ§€ 이동
	private static int[] taxi(int x, int y, int[] find) {
		Queue<int[]> queue = new LinkedList<>();
		queue.add(new int[] { x, y, 0 });
		visited[x][y] = true;

		while (!queue.isEmpty()) {
			int info[] = queue.poll();
			for (int i = 0; i < 4; i++) {
				int a = info[0] + dx[i];
				int b = info[1] + dy[i];
				if (a > 0 && a <= n && b > 0 && b <= n && arr[a][b] != 1 && !visited[a][b]) {
					visited[a][b] = true;
					if (a == find[0] && b == find[1]) {
						return new int[] { a, b, info[2] + 1 };
					}
					queue.add(new int[] { a, b, info[2] + 1 });
				}
			}
		}
		return new int[] { -1, -1, -1 };
	}
}
λ³€μˆ˜)
n : 격자 크기
m : μ†λ‹˜ 수
fuel : μ—°λ£Œ μ–‘
arr : 지도 정보
visited : λ°©λ¬Έ μ—¬λΆ€
x, y : μš΄μ „μ„ μ‹œμž‘ν•˜λŠ” 칸의 ν–‰ 번호, μ—΄ 번호 
idx : μ†λ‹˜ 번호
map : <μ†λ‹˜ 번호, μ†λ‹˜ λͺ©μ μ§€>
startX, startY, endX, endY : μ†λ‹˜μ˜ μΆœλ°œμ§€μ˜ ν–‰, μ—΄ 번호, λͺ©μ μ§€μ˜ ν–‰, μ—΄ 번호

 

Main

격자 크기, μ†λ‹˜ 수, μ—°λ£Œ 양을 μž…λ ₯λ°›λŠ”λ‹€. 지도 정보λ₯Ό μž…λ ₯λ°›μ•„ arr에 μ €μž₯ν•œλ‹€. μš΄μ „μ„ μ‹œμž‘ν•˜λŠ” μœ„μΉ˜λ₯Ό μž…λ ₯λ°›κ³ , μ†λ‹˜μ˜ μœ„μΉ˜λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. μ†λ‹˜μ˜ μœ„μΉ˜λ₯Ό μž…λ ₯λ°›μ•„ arr 지도에 μ†λ‹˜ 번호λ₯Ό μ €μž₯ν•˜κ³ , HashMap에 μ†λ‹˜ λ²ˆν˜Έμ™€ λͺ©μ μ§€ μœ„μΉ˜λ₯Ό μ €μž₯ν•œλ‹€.

 

μ—°λ£Œκ°€ λ‚¨μ•„μžˆλŠ” λ™μ•ˆ μ•„λž˜ 과정을 λ°˜λ³΅ν•œλ‹€.

1) λ°©λ¬Έ λ°°μ—΄ μ΄ˆκΈ°ν™”

2) findCustomer ν•¨μˆ˜λ₯Ό 톡해 ν˜„μž¬ μœ„μΉ˜μ—μ„œ κ°€μž₯ κ°€κΉŒμš΄ μ†λ‹˜ μœ„μΉ˜ κ΅¬ν•˜κΈ°

3) λ§Œμ•½ λͺ¨λ“  μ†λ‹˜ν•œν…Œ 이동할 수 μ—†λ‹€λ©΄ μ’…λ£Œ

4) κ°€κΉŒμš΄ μ†λ‹˜ν•œν…Œ 이동 ν›„ μ—°λ£Œ μ†Œλͺ¨. μ—°λ£Œκ°€ 0 μ΄ν•˜λΌλ©΄ λͺ©μ μ§€κΉŒμ§€ 이동할 수 μ—†μœΌλ―€λ‘œ μ’…λ£Œ

5) λ°©λ¬Έ λ°°μ—΄ μ΄ˆκΈ°ν™”

6) μ†λ‹˜μ„ νƒœμš°κ³  μ†λ‹˜ λͺ©μ μ§€κΉŒμ§€ 이동

7) λͺ©μ μ§€κΉŒμ§€ 이동할 수 μ—†λ‹€λ©΄ μ’…λ£Œ

8) λͺ©μ μ§€κΉŒμ§€ 이동 ν›„ μ—°λ£Œ μ†Œλͺ¨. λ§Œμ•½ 남은 μ—°λ£Œκ°€ 0보닀 μž‘λ‹€λ©΄ λͺ©μ μ§€κΉŒμ§€ 이동 λΆˆκ°€λŠ₯ν•œ κ²ƒμ΄λ―€λ‘œ μ’…λ£Œ. 남은 μ—°λ£Œκ°€  0 이상이라면 μ†Œλͺ¨ν•œ μ—°λ£Œ μ–‘μ˜ 두 λ°° μΆ©μ „

9) μ†λ‹˜ ν•œ λͺ…을 λͺ©μ μ§€κΉŒμ§€ μ΄λ™μ‹œν‚¨ κ²ƒμ΄λ―€λ‘œ m-1 및 ν˜„μž¬ μœ„μΉ˜ μ—…λ°μ΄νŠΈ

10) m이 0이라면 λͺ¨λ“  μ†λ‹˜μ„ λͺ©μ μ§€κΉŒμ§€ μ΄λ™μ‹œν‚¨ κ²ƒμ΄λ―€λ‘œ μ’…λ£Œ

 

λͺ¨λ“  μ†λ‹˜μ„ μ΄λ™μ‹œν‚¬ 수 μ—†κ±°λ‚˜ 이동 도쀑에 μ—°λ£Œκ°€ λ°”λ‹₯λ‚œ 경우 -1을 좜λ ₯ν•œλ‹€. κ·Έ μ™Έ λͺ¨λ“  μ†λ‹˜μ„ μ΄λ™μ‹œν‚€κ³  μ—°λ£Œλ₯Ό μΆ©μ „ν–ˆμ„ λ•Œ 남은 μ—°λ£Œμ˜ 양을 좜λ ₯ν•œλ‹€.

 

init

λ°©λ¬Έ λ°°μ—΄ viistedλ₯Ό false둜 μ΄ˆκΈ°ν™”ν•œλ‹€.

 

findCustomer (x, y)

: [μ†λ‹˜ μœ„μΉ˜, μ†λ‹˜ 번호, 거리] λ°˜ν™˜

μ‹œμž‘ μœ„μΉ˜μ— μ†λ‹˜μ΄ μžˆλ‹€λ©΄ κ°€μž₯ κ°€κΉŒμš΄ μ†λ‹˜μ΄λ―€λ‘œ 값을 λ°˜ν™˜ν•˜κ³  μ’…λ£Œν•œλ‹€.

queue에 [μ‹œμž‘ μœ„μΉ˜, 거리 0]을 μ €μž₯ν•˜λ©° μ‹œμž‘ μœ„μΉ˜λ₯Ό λ°©λ¬Έ ν‘œμ‹œν•œλ‹€. 

μš°μ„ μˆœμœ„ νλŠ” [μ†λ‹˜ μœ„μΉ˜ x, y, μ†λ‹˜ 번호, 거리]λ₯Ό μ €μž₯ν•˜λ©° 거리λ₯Ό μš°μ„ μˆœμœ„λ‘œ, 거리가 κ°™λ‹€λ©΄ μ†λ‹˜ μœ„μΉ˜μ˜ x, yλ₯Ό μš°μ„ μˆœμœ„λ‘œ λ‘”λ‹€.

 

queueκ°€ 빌 λ•ŒκΉŒμ§€ μ•„λž˜ 과정을 λ°˜λ³΅ν•œλ‹€.

1) queue poll

2) μƒμ’Œμš°ν•˜ νƒμƒ‰ν•˜μ—¬ 지도 λ²”μœ„ μ•ˆμ΄λ©° λΉ„μ–΄μžˆλŠ” 칸이며 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ€ 곳이라면 λ°©λ¬Έ ν‘œμ‹œν•œλ‹€. λ§Œμ•½ κ·Έ μœ„μΉ˜μ— μ†λ‹˜μ΄ μžˆλ‹€λ©΄ μš°μ„ μˆœμœ„ 큐가 λΉ„μ—ˆκ±°λ‚˜ μš°μ„ μˆœμœ„ 큐에 μžˆλŠ” κ°’μ˜ μ΅œλ‹¨κ±°λ¦¬λ³΄λ‹€ μž‘κ±°λ‚˜ κ°™λ‹€λ©΄ 값을 μΆ”κ°€ν•œλ‹€. μ†λ‹˜μ΄ μžˆκ±°λ‚˜ μ—†κ±°λ‚˜ queueμ—λŠ” 값을 μΆ”κ°€ν•œλ‹€.

 

μš°μ„ μˆœμœ„ 큐가 λΉ„μ—ˆλ‹€λ©΄ μ–΄λŠ μ†λ‹˜ν•œν…Œλ„ 갈 수 μ—†λ‹€λŠ” λœ»μ΄λ―€λ‘œ -1이 λ“  배열을 λ°˜ν™˜ν•œλ‹€. μš°μ„ μˆœμœ„ 큐에 값이 μžˆλ‹€λ©΄ poll ν•œ 값을 λ°˜ν™˜ν•œλ‹€. 

 

taxi (x, y, λ„μ°©μœ„μΉ˜ find)

: [μ†λ‹˜ μœ„μΉ˜, 거리] λ°˜ν™˜

queue에 [μ‹œμž‘ μœ„μΉ˜, 거리 0]을 μ €μž₯ν•˜λ©° μ‹œμž‘ μœ„μΉ˜λ₯Ό λ°©λ¬Έ ν‘œμ‹œν•œλ‹€.

 

queueκ°€ 빌 λ•ŒκΉŒμ§€ μ•„λž˜ 과정을 λ°˜λ³΅ν•œλ‹€.

1) queue poll

2) μƒμ’Œμš°ν•˜ νƒμƒ‰ν•˜μ—¬ 지도 λ²”μœ„ μ•ˆμ΄λ©° λΉ„μ–΄μžˆλŠ” 칸이며 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ„ 곳이라면 λ°©λ¬Έ ν‘œμ‹œν•œλ‹€. λ§Œμ•½ κ·Έ μœ„μΉ˜κ°€ 도착 μœ„μΉ˜λΌλ©΄ [도착 μœ„μΉ˜, 거리]λ₯Ό λ°˜ν™˜ν•œλ‹€. 도착 μœ„μΉ˜κ°€ μ•„λ‹ˆλΌλ©΄ queue에 값을 μ €μž₯ν•œ ν›„ κ³„μ†ν•œλ‹€.

 

λ§Œμ•½ 도착 μœ„μΉ˜μ— λ„λ‹¬ν•˜μ§€ λͺ»ν•œλ‹€λ©΄ -1이 λ“  배열을 λ°˜ν™˜ν•œλ‹€.