문제


 

 

 

풀이


문제를 이해하는데 시간이 좀 걸렸다. 최단 경로에서 고도 차가 아니라, 가장 낮은 고도차(피로도가 가장 적은)를 구하는 문제.

 

먼저, 입력받은 고도에 대해 중복없이 배열(리스트)에 저장한 후, 정렬한다.

정렬된 고도 값을 담은 1차원 배열에 대해 투 포인터를 잡고, BFS 탐색 조건을 건다.

    1) 다음으로 탐색할 땅의 고도가 투 포인터로 잡은 최저 고도보다 크거나 같고, 최고 고도보다 작거나 같다.

 

위의 탐색 조건으로 탐색을 끝낸 후, 모든 집을 방문했는지 여부를 확인한 다음 고도 차를 저장해 나간다.

 

 

 

코드


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static int N, houseNum, startX, startY, ans = 1_000_000;
private static char[][] map;
private static int[][] heightMap;
private static List<Integer> heightList = new ArrayList<>();
private static boolean[][] visited;
private static int[] dx = {-1, 1, 0, 0, -1, -1, 1, 1};
private static int[] dy = {0, 0, 1, -1, -1, 1, 1, -1};
static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) throws IOException {
N = Integer.parseInt(br.readLine());
heightMap = new int[N][N];
map = new char[N][N];
for (int i = 0; i < N; i++) {
String str = br.readLine();
for (int j = 0; j < N; j++) {
map[i][j] = str.charAt(j);
if (map[i][j] == 'K') {
houseNum++;
}
if (map[i][j] == 'P') {
startX = j;
startY = i;
}
}
}
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
heightMap[i][j] = Integer.parseInt(st.nextToken());
if (!heightList.contains(heightMap[i][j])) heightList.add(heightMap[i][j]);
}
}
Collections.sort(heightList);
bfs();
br.close();
}
public static void bfs() {
int low = 0, high = 0;
while (low < heightList.size()) {
visited = new boolean[N][N];
Queue<Node> queue = new LinkedList<>();
int val = heightMap[startY][startX];
if (heightList.get(low) <= val && val <= heightList.get(high)) {
visited[startY][startX] = true;
queue.add(new Node(startX, startY));
}
int count = 0;
while (!queue.isEmpty()) {
Node cur = queue.poll();
if (map[cur.y][cur.x] == 'K') count++;
for (int d = 0; d < 8; d++) {
int nx = cur.x + dx[d];
int ny = cur.y + dy[d];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
if (visited[ny][nx]) continue;
int nextVal = heightMap[ny][nx];
// 탐색의 조건에 해당한다.
// high 고도 - low 고도의 높이 차에 해당하는 땅만 밝아가며 탐색한다는 의미.
if (heightList.get(low) <= nextVal && nextVal <= heightList.get(high)) {
visited[ny][nx] = true;
queue.add(new Node(nx, ny));
}
}
}
if (houseNum == count) {
ans = Math.min(ans, heightList.get(high) - heightList.get(low));
low++;
} else if (high + 1 < heightList.size()) {
high++;
} else
break;
}
System.out.println(ans);
}
}

댓글

댓글을 사용할 수 없습니다.