문제
지훈이는 미로에서 일을 한다. 지훈이를 미로에서 탈출하도록 도와주자!
미로에서의 지훈이의 위치와 불이 붙은 위치를 감안해서 지훈이가 불에 타기전에 탈출할 수 있는지의 여부, 그리고 얼마나 빨리 탈출할 수 있는지를 결정해야한다.
지훈이와 불은 매 분마다 한칸씩 수평또는 수직으로(비스듬하게 이동하지 않는다) 이동한다.
불은 각 지점에서 네 방향으로 확산된다.
지훈이는 미로의 가장자리에 접한 공간에서 탈출할 수 있다.
지훈이와 불은 벽이 있는 공간은 통과하지 못한다.
입력
입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다.
다음 입력으로 R줄동안 각각의 미로 행이 주어진다.
각각의 문자들은 다음을 뜻한다. .#: 벽 .: 지나갈 수 있는 공간 J: 지훈이의 미로에서의 초기위치 (지나갈 수 있는 공간) F: 불이 난 공간 J는 입력에서 하나만 주어진다.
출력
지훈이가 불이 도달하기 전에 미로를 탈출 할 수 없는 경우 IMPOSSIBLE 을 출력한다.
지훈이가 미로를 탈출할 수 있는 경우에는 가장 빠른 탈출시간을 출력한다.
예제 입력 1
4 4
####
#JF#
#..#
#..#
예제 출력 1
3
package boj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
/**
* Created by mkhwang on 2021/04/04
* Email : orange2652@gmail.com
* Github : http://github.com/myeongkwonhwang
*/
public class Boj4179 {
static int R;
static int C;
static String maze[][];
static int[] dx = {1,0,-1,0};
static int[] dy = {0,1,0,-1};
static int[][] dist1; //불의전파시간
static int[][] dist2; //지훈이이동시간
//불이 있는곳은 통과하지 못하고 불이 옮겨지는 시간을 계산한다.
//불이 옮겨지는 시간을 계산해서 시간을 넣고 그 지훈이가 도달할수있는 위치가 있는지 확인
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine());
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
int count = 0;
Queue<Node> fireQueue = new LinkedList<>();
Queue<Node> jQueue = new LinkedList<>();
maze = new String[R][C];
dist1 = new int[R][C];
dist2 = new int[R][C];
for (int i = 0; i < R; i++) {
st = new StringTokenizer(bf.readLine());
String line = st.nextToken();
for (int j = 0; j < C; j++) {
maze[i][j] = String.valueOf(line.charAt(j));
dist1[i][j] = -1;
dist2[i][j] = -1;
if(line.charAt(j) == 'F') {
fireQueue.add(new Node(i,j));
dist1[i][j] = 0;
}
if(line.charAt(j) == 'J') {
jQueue.add(new Node(i,j));
dist2[i][j] = 0;
}
}
}
while (!fireQueue.isEmpty()){
Node curr = fireQueue.poll();
for (int dir = 0; dir < 4; dir++) {
int nx = curr.getX() + dx[dir];
int ny = curr.getY() + dy[dir];
if(nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
if(dist1[nx][ny] > -1 || maze[nx][ny].equals("#")) continue;
dist1[nx][ny] = dist1[curr.getX()][curr.getY()]+1;
fireQueue.add(new Node(nx, ny));
}
}
boolean isExit = false;
while (!jQueue.isEmpty() && !isExit){
Node curr = jQueue.poll();
for (int dir = 0; dir < 4; dir++){
int nx = curr.getX() + dx[dir];
int ny = curr.getY() + dy[dir];
if(nx < 0 || nx >= R || ny < 0 || ny >= C){
count = dist2[curr.getX()][curr.getY()]+1;
isExit = true;
break;
}
//이미 방문한 곳이거나 벽이면
if(dist2[nx][ny] >= 0 || maze[nx][ny].equals("#") || maze[nx][ny].equals("F")) continue;
//불전파 시간에 지훈이가 다음지나갈 곳에서 마주칠 수 있다면
if(dist1[nx][ny] != -1 && dist1[nx][ny] <= dist2[curr.getX()][curr.getY()]+1) continue;
dist2[nx][ny] = dist2[curr.getX()][curr.getY()]+1;
jQueue.add(new Node(nx, ny));
}
}
System.out.println(count == 0 ? "IMPOSSIBLE" : count);
}
public static class Node {
private int x;
private int y;
public Node (int x, int y){
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public int getX() {
return x;
}
}
}