길고 길었던 번아웃이 끝나고 드디어 공부할 맘이 점점 생겨가고 있다. 이제까지 집에서만 공부하려던 고집을 잠시 내려놓고 스터디카페, 카페 이곳저곳을 나돌아다니며 주변 환경을 바꿔보았다. 결과는 대성공이다. 환경이 변하니 그간의 번아웃이 사라지고 집중력이 아주 좋아졌다. 덕분에 평균 순공시간 7시간을 달성했다. 가끔은 지나가는 사람들 구경하느라 앞에 집중 못 할 적도 있었던 10월 셋째 주를 되돌아본다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
Solution s = new Solution();
System.out.println(s.solution(readInput(br)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static List<String[][][]> readInput(BufferedReader br) throws IOException {
List<String[][][]> result = new ArrayList<>();
int idx = 0;
while (true) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int floors = Integer.parseInt(st.nextToken());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
if(floors == 0 && x == 0 && y == 0) break;
result.add(new String[floors][x][y]);
for (int i = 0; i < floors; i++) {
for (int j = 0; j < x; j++) {
result.get(idx)[i][j] = br.readLine().split("");
}
br.readLine();
}
idx++;
}
return result;
}
}
class Solution {
public String solution(List<String[][][]> testCases) {
StringBuilder answer = new StringBuilder();
for (String[][][] testCase : testCases) {
Calculator c = new Calculator(testCase);
answer.append(c.getResult()).append("\n");
}
return answer.toString();
}
}
class Calculator {
private static final int[][] DIRECTIONS = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, -1}, {0, 0, 1}};
private final String[][][] map;
private final boolean[][][] isVisited;
private int[] startPoint;
private int[] endPoint;
private int time = 0;
public Calculator(String[][][] map) {
this.map = map;
this.isVisited = new boolean[map.length][map[0].length][map[0][0].length];
int floors = map.length;
int x = map[0].length;
int y = map[0][0].length;
for (int i = 0; i < floors; i++) {
for (int j = 0; j < x; j++) {
for (int k = 0; k < y; k++) {
if(map[i][j][k].equals("S")) startPoint = new int[]{i, j, k};
if(map[i][j][k].equals("E")) endPoint = new int[]{i, j, k};
if(startPoint != null && endPoint != null) return;
}
}
}
}
public String getResult() {
simulateEscape();
if(isFail()) return "Trapped!";
return "Escaped in " + time + " minute(s).";
}
private void simulateEscape() {
Queue<Location> q = new ArrayDeque<>();
Location startLocation = new Location(startPoint[0], startPoint[1], startPoint[2], 0);
q.offer(startLocation);
visit(startLocation);
while (!q.isEmpty()) {
Location cur = q.poll();
if (cur.isTargetLocation(endPoint)) {
this.time = cur.getTime();
return;
}
for (int[] direction : DIRECTIONS) {
int nfloor = cur.getFloor() + direction[0];
int nx = cur.getX() + direction[1];
int ny = cur.getY() + direction[2];
if (isWithinBuilding(nfloor, nx, ny) && isReachable(nfloor, nx, ny) && !isVisited[nfloor][nx][ny]) {
Location nextLocation = new Location(nfloor, nx, ny, cur.getTime() + 1);
visit(nextLocation);
q.offer(nextLocation);
}
}
}
}
private void visit(Location location) {
int floor = location.getFloor();
int x = location.getX();
int y = location.getY();
isVisited[floor][x][y] = true;
}
private boolean isFail() {
return time == 0;
}
private boolean isWithinBuilding(int z, int x, int y) {
return 0 <= z && z < map.length && 0 <= x && x < map[z].length && 0 <= y && y < map[z][x].length;
}
private boolean isReachable(int z, int x, int y) {
return map[z][x][y].equals(".") || map[z][x][y].equals("E");
}
private static class Location {
private final int floor;
private final int x;
private final int y;
private final int time;
public Location(int floor, int x, int y, int time) {
this.floor = floor;
this.x = x;
this.y = y;
this.time = time;
}
public boolean isTargetLocation(int[] targetPoint) {
return floor == targetPoint[0] && x == targetPoint[1] && y == targetPoint[2];
}
public int getFloor() {
return floor;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getTime() {
return time;
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
Solution s = new Solution();
System.out.println(s.solution(readInput(br)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static List<char[][]> readInput(BufferedReader br) throws IOException {
int len = Integer.parseInt(br.readLine());
List<char[][]> result = new ArrayList<>();
for (int i = 0; i < len; i++) {
String[] tokens = br.readLine().split(" ");
int x = Integer.parseInt(tokens[1]);
int y = Integer.parseInt(tokens[0]);
char[][] field = new char[x][y];
for (int j = 0; j < x; j++) {
field[j] = br.readLine().toCharArray();
}
result.add(field);
}
return result;
}
}
class Solution {
public String solution(List<char[][]> testCases) {
StringBuilder answer = new StringBuilder();
for (char[][] testCase : testCases) {
EscapeSimulator es = new EscapeSimulator(testCase);
answer.append(es.getResult()).append("\n");
}
return answer.toString();
}
}
class EscapeSimulator {
private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
private final char[][] building;
private final boolean[][] isVisited;
private final int[][] fireBoard;
private final Queue<int[]> humanLocation = new ArrayDeque<>();
private final Queue<int[]> fireLocation = new ArrayDeque<>();
private int result = Integer.MAX_VALUE;
public EscapeSimulator(char[][] building) {
this.building = building;
this.isVisited = new boolean[building.length][building[0].length];
this.fireBoard = new int[building.length][building[0].length];
for (int[] ints : fireBoard) {
Arrays.fill(ints, -1);
}
}
public String getResult() {
simulateEscape(init());
if(result == Integer.MAX_VALUE) return "IMPOSSIBLE";
return result + "";
}
private int[] init() {
int x = building.length;
int y = building[0].length;
int[] startPosition = new int[3];
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (building[i][j] == '@') {
isVisited[i][j] = true;
startPosition = new int[]{i, j, 0};
} else if (building[i][j] == '*') {
fireBoard[i][j] = 0;
fireLocation.add(new int[]{i, j, 0});
}
}
}
return startPosition;
}
private void simulateEscape(int[] startPosition) {
fireSimulate();
humanSimulate(startPosition);
}
private void fireSimulate() {
while (!fireLocation.isEmpty()) {
int[] cur = fireLocation.poll();
int x = cur[0];
int y = cur[1];
int time = cur[2];
for (int[] direction : DIRECTIONS) {
int nx = x + direction[0];
int ny = y + direction[1];
int ntime = time + 1;
if (isWithinBuilding(nx, ny) && (building[nx][ny] == '.' || building[nx][ny] == '@') && fireBoard[nx][ny] == -1) {
fireBoard[nx][ny] = ntime;
fireLocation.offer(new int[]{nx, ny, ntime});
}
}
}
}
private void humanSimulate(int[] startPosition) {
int startX = startPosition[0];
int startY = startPosition[1];
humanLocation.offer(startPosition);
isVisited[startX][startY] = true;
while (!humanLocation.isEmpty()) {
int[] cur = humanLocation.poll();
int x = cur[0];
int y = cur[1];
int time = cur[2];
for (int[] direction : DIRECTIONS) {
int nx = x + direction[0];
int ny = y + direction[1];
int ntime = time + 1;
if (isOutOfBuilding(nx, ny)) {
result = Math.min(result, ntime);
return;
}
if (isWithinBuilding(nx, ny) && building[nx][ny] == '.' && (fireBoard[nx][ny] > ntime || fireBoard[nx][ny] == -1) && !isVisited[nx][ny]) {
isVisited[nx][ny] = true;
humanLocation.offer(new int[]{nx, ny, ntime});
}
}
}
}
private boolean isOutOfBuilding(int x, int y) {
return x < 0 || x >= building.length || y < 0 || y >= building[x].length;
}
private boolean isWithinBuilding(int x, int y) {
return 0 <= x && x < building.length && 0 <= y && y < building[x].length;
}
}