[백준 2842 : JAVA] 집배원 한상덕 / BFS + 투 포인터
문제
풀이
문제를 이해하는데 시간이 좀 걸렸다. 최단 경로에서 고도 차가 아니라, 가장 낮은 고도차(피로도가 가장 적은)를 구하는 문제.
먼저, 입력받은 고도에 대해 중복없이 배열(리스트)에 저장한 후, 정렬한다.
정렬된 고도 값을 담은 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);
}
}
'Algorithm > Baekjoon' 카테고리의 다른 글
[백준 15684 : JAVA] 사다리 조작 / 백트래킹 (0) | 2020.11.08 |
---|---|
[백준 6549 : JAVA] 히스토그램에서 가장 큰 직사각형 / 세그먼트 트리 +분할정복 (0) | 2020.11.02 |
[백준 2531 : JAVA] 회전 초밥 / 투 포인터 (0) | 2020.10.26 |
[백준 1854 : JAVA] K번째 최단경로 찾기 / 다익스트라 (1) | 2020.10.23 |
[백준 1238 : JAVA] 파티 / 다익스트라 (0) | 2020.10.22 |
댓글
이 글 공유하기
다른 글
-
[백준 15684 : JAVA] 사다리 조작 / 백트래킹
[백준 15684 : JAVA] 사다리 조작 / 백트래킹
2020.11.08 -
[백준 6549 : JAVA] 히스토그램에서 가장 큰 직사각형 / 세그먼트 트리 +분할정복
[백준 6549 : JAVA] 히스토그램에서 가장 큰 직사각형 / 세그먼트 트리 +분할정복
2020.11.02 -
[백준 2531 : JAVA] 회전 초밥 / 투 포인터
[백준 2531 : JAVA] 회전 초밥 / 투 포인터
2020.10.26 -
[백준 1854 : JAVA] K번째 최단경로 찾기 / 다익스트라
[백준 1854 : JAVA] K번째 최단경로 찾기 / 다익스트라
2020.10.23