각 점의 영역을 표시해야할 때 각 점을 동시에 BFS
Multi-Source BFS
- 제목
시루의 백화점 구경
- 조건
시간 제한 : 2 초
메모리 제한 : 1024 MB
- 문제
시루는 부모님과 함께 백화점에 갔다. 부모님은 쇼핑할 것이 많기 때문에 여러 곳을 돌아다녀야 하고, 시루는 부모님과 함께 걸어다니는 것이 너무 힘들어서 의자에 앉아서 쉬려고 한다.
백화점은 세로 길이가 N, 가로 길이가 M인 격자 형태이고, 상하좌우로 인접한 칸으로 이동할 때마다 1 만큼의 체력을 소모한다. 시루는 현재 위치에서 출발해 백화점 곳곳에 있는 의자 중 하나를 찾아가서 앉으려고 한다. 시루는 백화점 밖으로 나가면 부모님께 혼나기 때문에 백화점 밖으로 나갈 수 없다.
백화점에는 건물을 지탱하기 위한 기둥과 옷을 전시하기 위한 마네킹이 있다. 시루는 기둥이 있는 칸으로 이동하지 못하고, 마네킹을 무서워하기 때문에 마네킹과 거리가 K 이하인 칸은 사용하지 않으려고 한다. 이때 두 칸 (rx, cx), (ry, cy)의 거리는 | rx - ry | + | cx - cy |이다. 단, 시루가 출발할 때는 부모님과 함께 있기 때문에, 출발 지점과 마네킹과의 거리가 K 이하가 되어도 출발할 수 있다.
시루는 다리가 너무 아프기 때문에 체력 소모를 최소화하면서 의자까지 찾아가려고 한다. 시루가 소모하는 체력의 최솟값을 구해보자.
- 입력
첫째 줄에 백화점의 세로 길이, 가로 길이, 마네킹과 떨어져야 하는 거리를 의미하는 정수 N, M, K가 공백으로 구분되어 주어진다. (1 ≤ N,M ≤ 2,000, 0 ≤ K ≤ 4,000)
둘째 줄부터 N개의 줄에 각각 M개씩 위에서부터 차례로 백화점의 상태가 주어진다. 아무것도 없는 칸은 0, 기둥이 있는 칸은 1, 의자가 있는 칸은 2, 마네킹이 있는 칸은 3, 시루의 시작 위치는 4로 주어진다. 시루의 시작 위치는 정확히 한 번 주어지고, 해당 위치에 기둥, 의자, 마네킹이 존재하지 않는다.
- 출력
시루가 의자를 찾아갈 수 있다면 시루가 소모하는 체력의 최솟값을 출력한다.
만약 의자를 찾아갈 수 없다면 -1을 출력한다.
예제 입력1 | 예제 출력1 |
5 5 1 0 0 0 0 4 0 0 0 1 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 2 |
8 |
예제 입력2 | 예제 출력2 |
5 5 2 0 0 0 0 4 0 0 0 1 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 2 |
-1 |
예제 입력3 | 예제 출력3 |
5 5 2 2 0 0 0 4 0 0 0 1 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 |
4 |
예제 입력4 | 예제 출력4 |
5 5 0 0 0 0 0 4 0 0 0 1 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 |
-1 |
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringBuilder sb = new StringBuilder();
static StringTokenizer st;
static int N, M, K, SIRU;
static int[][] arr, dist;
static ArrayList<Integer> mannequin, chair;
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
static void mannequinBFS() {
boolean[][] visited = new boolean[N][M];
Queue<int[]> queue = new ArrayDeque<>();
for (int i = 0; i < mannequin.size(); i++) {
queue.add(new int[]{mannequin.get(i), K});
visited[mannequin.get(i) / M][mannequin.get(i) % M] = true;
}
while (!queue.isEmpty()) {
int[] curr = queue.poll();
int x = curr[0] / M;
int y = curr[0] % M;
int hp = curr[1];
if(hp == 0) continue;
for (int k = 0; k < 4; k++) {
int tx = x + dx[k];
int ty = y + dy[k];
if(tx < 0 || ty < 0 || tx >= N || ty >= M) continue;
if(visited[tx][ty]) continue;
queue.add(new int[]{tx * M + ty, hp - 1});
visited[tx][ty] = true;
arr[tx][ty] = 3;
}
}
}
static void siruBFS() {
Queue<Integer> queue = new ArrayDeque<>();
dist[SIRU / M][SIRU % M] = 0;
queue.add(SIRU);
while (!queue.isEmpty()) {
int curr = queue.poll();
int x = curr / M;
int y = curr % M;
for (int k = 0; k < 4; k++) {
int tx = x + dx[k];
int ty = y + dy[k];
int next = tx * M + ty;
if (tx < 0 || ty < 0 || tx >= N || ty >= M) continue;
if (arr[tx][ty] == 1 || arr[tx][ty] == 3) continue;
if (dist[tx][ty] <= dist[x][y] + 1) continue;
dist[tx][ty] = dist[x][y] + 1;
queue.add(next);
}
}
}
public static void main(String[] args) throws IOException {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
arr = new int[N][M];
dist = new int[N][M];
chair = new ArrayList<>();
mannequin = new ArrayList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
dist[i][j] = Integer.MAX_VALUE;
if (arr[i][j] == 2) chair.add(i * M + j);
if (arr[i][j] == 3) mannequin.add(i * M + j);
if (arr[i][j] == 4) SIRU = i * M + j;
}
}
mannequinBFS();
siruBFS();
int answer = Integer.MAX_VALUE;
for (int i = 0; i < chair.size(); i++) {
int x = chair.get(i) / M;
int y = chair.get(i) % M;
answer = Math.min(answer, dist[x][y]);
}
System.out.println(answer == Integer.MAX_VALUE ? -1 : answer);
}
}
'Problem Solving > BaekJoon' 카테고리의 다른 글
[BOJ/백준] 27212 - 미팅 (0) | 2024.03.07 |
---|---|
[BOJ/백준] 31477 - 양갈래 구하기 (1) | 2024.03.06 |
[BOJ/백준] 30640 - 운전 연습 (1) | 2024.03.05 |
[BOJ/백준] 30680 - 별자리 만들기 (0) | 2024.02.29 |
[BOJ/백준] 25395 - 커넥티드 카 실험 (0) | 2024.02.28 |