Skip to content

Commit 6efbf38

Browse files
committed
[20250204] BOJ / 골드2 / 등산 / 신동윤
1 parent f5643eb commit 6efbf38

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
```java
2+
import java.io.*;
3+
import java.util.*;
4+
5+
public class Main {
6+
7+
private static class Node implements Comparable<Node>{
8+
int r;
9+
int c;
10+
int weight;
11+
public Node(int r, int c, int weight) {
12+
this.r = r;
13+
this.c = c;
14+
this.weight = weight;
15+
}
16+
17+
public String toString() {
18+
return "(" + r + ", " + c + ", time:" + weight + ")";
19+
}
20+
21+
@Override
22+
public int compareTo(Node o) {
23+
return Integer.compare(this.weight, o.weight);
24+
}
25+
}
26+
27+
private static int N;
28+
private static int M;
29+
private static int T;
30+
private static int D;
31+
private static int[][] arr;
32+
private static int[] dr = {0, 0, -1, 1};
33+
private static int[] dc = {-1, 1, 0, 0};
34+
private static final int INF = Integer.MAX_VALUE;
35+
private static List<List<Node>> graph;
36+
37+
public static void main(String[] args) throws IOException {
38+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
39+
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
40+
41+
StringTokenizer st = new StringTokenizer(br.readLine());
42+
N = Integer.parseInt(st.nextToken());
43+
M = Integer.parseInt(st.nextToken());
44+
T = Integer.parseInt(st.nextToken());
45+
D = Integer.parseInt(st.nextToken());
46+
47+
arr = new int[N][M];
48+
for (int i = 0; i < N; i++) {
49+
char[] tmpChar = br.readLine().toCharArray();
50+
for (int j = 0; j < M; j++) {
51+
if (Character.isLowerCase(tmpChar[j])) {
52+
arr[i][j] = tmpChar[j] - 'a' + 26;
53+
} else {
54+
arr[i][j] = tmpChar[j] - 'A';
55+
}
56+
}
57+
}
58+
59+
// 인접리스트 생성
60+
graph = new ArrayList<>();
61+
for (int i = 0; i < N * M; i++) {
62+
graph.add(new ArrayList<>());
63+
}
64+
for (int r = 0; r < N; r++) {
65+
for (int c = 0; c < M; c++) {
66+
67+
int index = r * M + c;
68+
69+
for (int i = 0; i < 4; i++) {
70+
int nr = r + dr[i];
71+
int nc = c + dc[i];
72+
if (nr < 0 || nr >= N || nc < 0 || nc >= M) {
73+
continue;
74+
}
75+
76+
// 높이의 차이가 T보다 크지 않은 곳으로만 다닐 수 있다.
77+
if (Math.abs(arr[nr][nc] - arr[r][c]) > T) {
78+
continue;
79+
}
80+
81+
int time;
82+
if (arr[r][c] >= arr[nr][nc]) {
83+
time = 1;
84+
} else {
85+
time = (int)Math.pow(arr[nr][nc] - arr[r][c], 2);
86+
}
87+
88+
graph.get(index).add(new Node(nr, nc, time));
89+
}
90+
91+
}
92+
}
93+
94+
// 시작점 0에서 각 점까지의 최단거리
95+
int[] dist = dijkstra(new Node(0, 0, 0));
96+
97+
// 시작점에서 최단경로가 존재하는 정점 중, 제한 시간 내에 다시 시작점으로 돌아올 수 있는 경우
98+
int highest = arr[0][0];
99+
for (int mountain = 1; mountain < N*M; mountain++) {
100+
if (dist[mountain] != INF) {
101+
int mountC = mountain % M;
102+
int mountR = mountain / M;
103+
104+
if (highest >= arr[mountR][mountC]) continue;
105+
106+
int[] backDist = dijkstra(new Node(mountR, mountC, 0));
107+
if (dist[mountain] + backDist[0] <= D) {
108+
highest = arr[mountR][mountC];
109+
}
110+
}
111+
}
112+
113+
bw.write(highest + "\n");
114+
115+
br.close();
116+
bw.flush();
117+
bw.close();
118+
}
119+
120+
private static int[] dijkstra(Node start) {
121+
int[] dist = new int[N * M];
122+
Arrays.fill(dist, INF);
123+
124+
int startIdx = start.r * M + start.c;
125+
dist[startIdx]= 0;
126+
127+
PriorityQueue<Node> pq = new PriorityQueue<>();
128+
pq.offer(start);
129+
130+
while (!pq.isEmpty()) {
131+
Node node = pq.poll();
132+
int nodeIdx = node.r * M + node.c;
133+
134+
List<Node> nextNodes = graph.get(nodeIdx);
135+
for (Node nextNode : nextNodes) {
136+
int nextIdx = nextNode.r * M + nextNode.c;
137+
int nextDist = dist[nodeIdx] + nextNode.weight;
138+
if (nextDist < dist[nextIdx]) {
139+
dist[nextIdx] = nextDist;
140+
pq.offer(new Node(nextNode.r, nextNode.c, nextDist));
141+
}
142+
}
143+
}
144+
145+
return dist;
146+
}
147+
}
148+
```
149+
- 주어진 입력을 인접 리스트 형태의 그래프로 변환
150+
- 시작점에서 dijkstra로 최단경로를 구한 뒤, 각 정점에서 시작점으로 제한시간 내에 돌아올 수 있는지 한번 더 체크
151+
- 유의사항
152+
- 시작점의 높이가 가장 높은 경우도 있을 수 있음
153+
- `highest`를 0으로 초기화하는 것이 아니라 시작점의 높이로 초기화
154+
- 테스트케이스
155+
```
156+
3 3 51 1000
157+
zAA
158+
AAA
159+
AAA
160+
```

0 commit comments

Comments
 (0)