Java

[백준] 19238 : 스타트택시

프로버티기 2025. 3. 7. 14:37

문제

https://www.acmicpc.net/problem/19238

 

 

 

입출력

 

 

 


아이디어

 

- 시뮬레이션

1. bfs로 택시 현재 위치에서 가장 가까운 거리에 있는 손님 찾기 

2. 그 위치로 택시를 옮기고 사람을 옮기는 로직 수행 (이때 연료 확인)

 

코드 

 

 

 

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

public class Main {
    static int N, M, fuel;
    static int[][] box;
    static int[][] personToId;
    static int[] car;
    static int[][] routes;
    static final int INF = Integer.MAX_VALUE;
    static int[][] way = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } };

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        fuel = Integer.parseInt(st.nextToken());
        box = new int[N][N];

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

        st = new StringTokenizer(br.readLine());
        car = new int[]{Integer.parseInt(st.nextToken()) - 1, Integer.parseInt(st.nextToken()) - 1};

        personToId = new int[N][N];
        routes = new int[M + 1][5];

        for (int m = 1; m <= M; m++) {
            st = new StringTokenizer(br.readLine());
            int sx = Integer.parseInt(st.nextToken()) - 1;
            int sy = Integer.parseInt(st.nextToken()) - 1;
            int ex = Integer.parseInt(st.nextToken()) - 1;
            int ey = Integer.parseInt(st.nextToken()) - 1;
            routes[m] = new int[]{sx, sy, ex, ey, bfs(sx, sy, ex, ey)};
            personToId[sx][sy] = m;
        }

        while (true) {
            int[] person = findNear();
            if (person[0] == -1 || routes[person[0]][4] == INF || fuel < person[1]) break;
            
            fuel -= person[1];
            car[0] = routes[person[0]][0];
            car[1] = routes[person[0]][1];

            if (fuel < routes[person[0]][4]) break;
            
            fuel += routes[person[0]][4];
            car[0] = routes[person[0]][2];
            car[1] = routes[person[0]][3];
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (personToId[i][j] > 0) {
                    System.out.println(-1);
                    return;
                }
            }
        }
        System.out.println(fuel);
    }

    static int bfs(int sx, int sy, int ex, int ey) {
        boolean[][] visited = new boolean[N][N];
        Queue<int[]> queue = new ArrayDeque<>();
        queue.add(new int[]{sx, sy, 0});
        visited[sx][sy] = true;

        while (!queue.isEmpty()) {
            int[] now = queue.poll();
            if (now[0] == ex && now[1] == ey) return now[2];
            
            for (int[] dir : way) {
                int nx = now[0] + dir[0];
                int ny = now[1] + dir[1];
                if (nx < 0 || nx >= N || ny < 0 || ny >= N || visited[nx][ny] || box[nx][ny] == 1) continue;
                visited[nx][ny] = true;
                queue.add(new int[]{nx, ny, now[2] + 1});
            }
        }
        return INF;
    }

    static int[] findNear() { // 우선순위 비교에 PriorityQueue 사용
        boolean[][] visited = new boolean[N][N];
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[2] != b[2] ? a[2] - b[2] : a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
        pq.add(new int[]{car[0], car[1], 0});
        visited[car[0]][car[1]] = true;

        while (!pq.isEmpty()) {
            int[] now = pq.poll();
            if (personToId[now[0]][now[1]] > 0) {
                int id = personToId[now[0]][now[1]];
                personToId[now[0]][now[1]] = -1;
                return new int[]{id, now[2]};
            }
            
            for (int[] dir : way) {
                int nx = now[0] + dir[0];
                int ny = now[1] + dir[1];
                if (nx < 0 || nx >= N || ny < 0 || ny >= N || visited[nx][ny] || box[nx][ny] == 1) continue;
                visited[nx][ny] = true;
                pq.add(new int[]{nx, ny, now[2] + 1});
            }
        }
        return new int[]{-1, INF};
    }
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	static int N, M, fuel; // 라운드의수
	static int[][] box;
	static int[][] personToId;
	static int[] car; // 운전 시작하는 칸 번호, 열 번호
	static int[][] routes;

	public static void main(String[] args) throws IOException {
		System.setIn(new FileInputStream("src/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		fuel = Integer.parseInt(st.nextToken());
		box = new int[N][N];

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

		st = new StringTokenizer(br.readLine());
		car = new int[2];
		car[0] = Integer.parseInt(st.nextToken()) - 1;
		car[1] = Integer.parseInt(st.nextToken()) - 1;

		personToId = new int[N][N];
		routes = new int[M + 1][5];
		for (int m = 1; m <= M; m++) { // 승객의 출발지와 행과 번호, 목적지의 행과 열 번호
			st = new StringTokenizer(br.readLine());
			int sx = Integer.parseInt(st.nextToken()) - 1;
			int sy = Integer.parseInt(st.nextToken()) - 1;
			int ex = Integer.parseInt(st.nextToken()) - 1;
			int ey = Integer.parseInt(st.nextToken()) - 1;
			routes[m][0] = sx;
			routes[m][1] = sy;
			routes[m][2] = ex;
			routes[m][3] = ey;
			routes[m][4] = bfs(sx, sy, ex, ey); // 번호
			personToId[sx][sy] = m;

		}
		// i, j -> id ?
		while (true) {
			int[] person = findNear();
			if (person[0] == -1 || routes[person[0]][4] == Integer.MAX_VALUE) {
				break;
			}
			if (fuel - person[1] < 0) {
				break;
			}

			fuel -= person[1];// 승객 위치로 이동
			car[0] = routes[person[0]][0];
			car[1] = routes[person[0]][1];

			if (fuel < routes[person[0]][4]) { // 이동하는 도중에 연료가 바닥나면 이동에 실패
				break;
			}

			fuel += routes[person[0]][4]; // 거리 * 2 충전
			car[0] = routes[person[0]][2];
			car[1] = routes[person[0]][3];

		}

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (personToId[i][j] > 0) {
					System.out.println(-1);
					return;
				}
			}
		}

		System.out.println(fuel);

	}

	static int[][] way = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } };

	static int bfs(int sx, int sy, int ex, int ey) {
		boolean[][] visited = new boolean[N][N];
		Queue<int[]> queue = new ArrayDeque<>();
		visited[sx][sy] = true;
		queue.add(new int[] { sx, sy, 0 });

		while (!queue.isEmpty()) {
			int[] now = queue.poll();
			if (now[0] == ex && now[1] == ey) {
				return now[2];
			}
			for (int w = 0; w < 4; w++) {
				int nx = now[0] + way[w][0];
				int ny = now[1] + way[w][1];
				if (nx < 0 || nx >= N || ny < 0 || ny >= N || visited[nx][ny])
					continue;
				if (box[nx][ny] == 1)
					continue;
				visited[nx][ny] = true;
				queue.add(new int[] { nx, ny, now[2] + 1 });
			}
		}
		return Integer.MAX_VALUE;
	}

	static int[] findNear() {
		boolean[][] visited = new boolean[N][N];

		int minDist = Integer.MAX_VALUE, rowId = N, colId = N, id = -1;
		Queue<int[]> queue = new ArrayDeque<>();
		queue.add(new int[] { car[0], car[1], 0 });
		visited[car[0]][car[1]] = true;

		while (!queue.isEmpty()) {
			int[] now = queue.poll();
			if (personToId[now[0]][now[1]] > 0) {
				if (minDist > now[2] || minDist == now[2] && (rowId > now[0] || rowId == now[0] && colId > now[1])) {
					minDist = now[2];
					id = personToId[now[0]][now[1]];
					rowId = now[0];
					colId = now[1];
				}
			}
			for (int w = 0; w < 4; w++) {
				int nx = now[0] + way[w][0];
				int ny = now[1] + way[w][1];
				if (nx < 0 || nx >= N || ny < 0 || ny >= N || visited[nx][ny]) {
					continue;
				}
				if (box[nx][ny] == 1)
					continue;
				visited[nx][ny] = true;
				queue.add(new int[] { nx, ny, now[2] + 1 });
			}
		}
		if (id > 0) {
			personToId[rowId][colId] = -1;
		}
		return new int[] { id, minDist };

	}

}

'Java' 카테고리의 다른 글

[코드트리] 부분 수열의 합(DP)  (0) 2025.03.08
[백준] 17837 : 새로운 게임 2  (0) 2025.03.07
[백준] 17135 : 캐슬 디펜스  (0) 2025.03.07
[백준] 19942: 다이어트  (0) 2025.03.03
[백준] 1799 : 비숍  (0) 2025.03.03