문제
https://softeer.ai/practice/7726
자세한 내용은 원문 코드를 참조할 것.
풀이
유령이 과연 남우를 잡을 수 있을까? 에 대한 풀이는 간단하다.
BFS를 사용하여, '벽을 뚫을 수 있는' 유령의 최단거리보다 남우의 '최단거리' 가 짧으면 된다.
따라서, BFS를 유령 / 남우, 두 번씩 비교하여 최소값을 비교하면 된다.
여기서 시간 초과가 발생할 수 있는데, BFS의 범위 스코프를 '유령' 값의 스코프를 통해 비교해주면 된다.
전체 탐색의 경우 2.08초(처음에 시간 초과가 발생했다)였으나, 풀이 이후 0.1초 이내로 풀 수 있었다.
하위 코드에서는 'ghostDist'를 통해 스코프를 제한했다.
아래 코드에서 해당 프로퍼티를 중심으로 해석하면 쉬울 것이다.
코드
import java.io.*;
import java.util.*;
public class Main {
static final int[] DR = {-1, 0, 1, 0};
static final int[] DC = {0, -1, 0, 1};
static int N, M;
static boolean[][] map;
static int[][] ghostDist;
static boolean[][] visit;
static int[] player;
static int[] exit;
static List<int[]> ghosts = new ArrayList<>();
public static void main(String[] args) throws Exception {
input();
logic();
}
public static void logic() {
bfsGhosts(); // 유령들의 최소 거리 계산
int minPlayerDist = bfsPlayer(); // 남우의 최소 거리 계산
if (minPlayerDist == Integer.MAX_VALUE) {
System.out.println("No");
} else {
System.out.println("Yes");
}
}
public static void bfsGhosts() {
Queue<int[]> bfsQ = new ArrayDeque<>();
ghostDist = new int[N][M];
for (int[] row : ghostDist) Arrays.fill(row, Integer.MAX_VALUE);
for (int[] ghost : ghosts) {
bfsQ.offer(new int[]{ghost[0], ghost[1], 0});
ghostDist[ghost[0]][ghost[1]] = 0;
}
while (!bfsQ.isEmpty()) {
int[] now = bfsQ.poll();
int r = now[0], c = now[1], dist = now[2];
for (int i = 0; i < 4; i++) {
int nr = r + DR[i], nc = c + DC[i];
if (cantGo(nr, nc) || dist + 1 >= ghostDist[nr][nc]) continue;
ghostDist[nr][nc] = dist + 1;
bfsQ.offer(new int[]{nr, nc, dist + 1});
}
}
}
public static int bfsPlayer() {
Queue<int[]> bfsQ = new ArrayDeque<>();
visit = new boolean[N][M];
bfsQ.offer(new int[]{player[0], player[1], 0});
visit[player[0]][player[1]] = true;
while (!bfsQ.isEmpty()) {
int[] now = bfsQ.poll();
int r = now[0], c = now[1], dist = now[2];
if (r == exit[0] && c == exit[1]) return dist;
for (int i = 0; i < 4; i++) {
int nr = r + DR[i], nc = c + DC[i];
if (cantGo(nr, nc) || visit[nr][nc] || map[nr][nc] || dist + 1 >= ghostDist[nr][nc]) continue;
visit[nr][nc] = true; // 방문 체크를 큐에 추가하기 전에 수행
bfsQ.offer(new int[]{nr, nc, dist + 1});
}
}
return Integer.MAX_VALUE;
}
public static boolean cantGo(int r, int c) {
return r < 0 || c < 0 || r >= N || c >= M;
}
public static void input() throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new boolean[N][M];
for (int i = 0; i < N; i++) {
String s = br.readLine();
for (int j = 0; j < M; j++) {
char now = s.charAt(j);
if (now == '.') map[i][j] = false;
else if (now == '#') map[i][j] = true;
else if (now == 'D') exit = new int[]{i, j};
else if (now == 'N') player = new int[]{i, j};
else if (now == 'G') ghosts.add(new int[]{i, j});
}
}
}
}
'알고리즘 > 소프티어' 카테고리의 다른 글
[소프티어] 함께하는 효도 LV.3 (0) | 2024.06.29 |
---|