문제
3055번: 탈출 (acmicpc.net)
해결방법
- BFS 각각 BFS 단계별로 진행하며 먼저 해당 단계의 물을 퍼트리고 해당 단계의 고슴도치가 이동할 수 있는 위치를 모두 구한다. 그 때 고슴도치가 이동할 다음 위치가 D에 해당하면 전체 반복문을 종료한다.
- 주의점 문제에서 고슴도치는 물이 찰 예정인 칸으로 이동할 수 없다. 라고 되어 있으니 BFS를 수행하며 물의 위치를 먼저 구해 놓고 고슴도치가 이동 가능한 칸을 구해야 한다.
동작과정
- 고슴도치의 초기 위치와 물들의 초기 위치를 저장한다.
- 전체 반복문을 돌면서 단계를 저장하고 먼저 퍼뜨릴 물들을 받아와서 맵에 물을 퍼뜨린다.
- 그 후 현재 단계에 존재할 수 있는 고슴도치의 위치들에 대해 다음 위치를 찾는다. 이때 비버의 굴을 발견하면 현재의 단계 + 1을 결과로 주고 전체 반복문을 종료한다.
- 출력 시
result
값이 Integer.MAX_VALUE
라는 것은 고슴도치가 비버의 굴에 도달하지 못한 것이므로 KAKTUS
를 출력한다.
코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
private static class Point {
int y;
int x;
public Point(int y, int x) {
this.y = y;
this.x = x;
}
}
private final static int[][] D = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(in.readLine());
int R = Integer.parseInt(st.nextToken());
int C = Integer.parseInt(st.nextToken());
char[][] map = new char[R][C];
boolean[][] visited = new boolean[R][C];
Point start = null;
Queue<Point> waters = new ArrayDeque<>();
for (int i = 0; i < R; i++) {
String line = in.readLine();
for (int j = 0; j < C; j++) {
map[i][j] = line.charAt(j);
if (map[i][j] == 'S') {
start = new Point(i, j);
map[i][j] = '.';
}
else if(map[i][j] == '*') {
waters.offer(new Point(i, j));
}
}
}
Queue<Point> q = new ArrayDeque<>();
q.offer(start);
int result = Integer.MAX_VALUE;
int step = 0;
external: while (!q.isEmpty()) {
List<Point> newWaters = new ArrayList<>();
while(!waters.isEmpty()) {
Point water = waters.poll();
for (int d = 0; d < 4; d++) {
int wy = water.y + D[d][0];
int wx = water.x + D[d][1];
if (isInBound(wy, wx, R, C) && map[wy][wx] == '.') {
newWaters.add(new Point(wy, wx));
map[wy][wx] = '*';
}
}
}
for(Point water : newWaters)
waters.offer(water);
List<Point> list = new ArrayList<>();
while (!q.isEmpty()) {
Point now = q.poll();
for (int d = 0; d < 4; d++) {
int sy = now.y + D[d][0];
int sx = now.x + D[d][1];
if (isInBound(sy, sx, R, C) && !visited[sy][sx]) {
if (map[sy][sx] == '.') {
list.add(new Point(sy, sx));
visited[sy][sx] = true;
}
else if (map[sy][sx] == 'D') {
result = step + 1;
break external;
}
}
}
}
for(Point p : list)
q.add(p);
step++;
}
if(result == Integer.MAX_VALUE)
out.write("KAKTUS");
else
out.write(result+"");
out.flush();
}
private static boolean isInBound(int y, int x, int R, int C) {
if (y >= 0 && y < R && x >= 0 && x < C)
return true;
else
return false;
}
}