Skip to content

Commit c1ee29c

Browse files
authored
Merge pull request #1532 from AlgorithmWithGod/lkhyun
[20251128] BOJ / P5 / 바리스타의 힘 / 이강현
2 parents f6bddd4 + 85103aa commit c1ee29c

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
```java
2+
import java.util.*;
3+
import java.io.*;
4+
5+
public class Main{
6+
static class State{
7+
int i,j,cnt;
8+
State(int i,int j, int cnt){
9+
this.i = i;
10+
this.j = j;
11+
this.cnt = cnt;
12+
}
13+
}
14+
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
15+
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
16+
static StringTokenizer st;
17+
static StringBuilder sb = new StringBuilder();
18+
static int N,M;
19+
static int[][] map;
20+
static int[] di = {-1, 1, 0, 0};
21+
static int[] dj = {0, 0, -1, 1};
22+
static int ans = Integer.MAX_VALUE;
23+
24+
public static void main(String[] args) throws Exception {
25+
st = new StringTokenizer(br.readLine());
26+
N = Integer.parseInt(st.nextToken());
27+
M = Integer.parseInt(st.nextToken());
28+
29+
map = new int[N+1][M+1];
30+
31+
for(int i = 1; i<=N; i++){
32+
String line = br.readLine();
33+
for(int j = 1; j<=M; j++){
34+
map[i][j] = Character.getNumericValue(line.charAt(j-1));
35+
}
36+
}
37+
38+
BFS();
39+
bw.write((ans == Integer.MAX_VALUE ? -1 : ans) + "");
40+
bw.close();
41+
}
42+
43+
public static void BFS(){
44+
int[][][] dist = new int[N+1][M+1][2];
45+
for(int i = 0; i <= N; i++){
46+
for(int j = 0; j <= M; j++){
47+
dist[i][j][0] = -1;
48+
dist[i][j][1] = -1;
49+
}
50+
}
51+
52+
int[] leftmostInRow = new int[N+1];
53+
Arrays.fill(leftmostInRow, -1);
54+
55+
int[] topmostInCol = new int[M+1];
56+
Arrays.fill(topmostInCol, -1);
57+
58+
ArrayDeque<State> q = new ArrayDeque<>();
59+
60+
//출발지에서 BFS
61+
q.offer(new State(1, 1, 0));
62+
dist[1][1][0] = 0;
63+
leftmostInRow[1] = 1;
64+
topmostInCol[1] = 1;
65+
66+
while(!q.isEmpty()){
67+
State cur = q.poll();
68+
69+
for(int d = 0; d < 4; d++){
70+
int ni = cur.i + di[d];
71+
int nj = cur.j + dj[d];
72+
73+
if(OOB(ni, nj)) continue;
74+
if(map[ni][nj] == 1) continue;
75+
if(dist[ni][nj][0] != -1) continue;
76+
77+
dist[ni][nj][0] = cur.cnt + 1;
78+
q.offer(new State(ni, nj, cur.cnt + 1));
79+
80+
//현재 행에서 가장 왼쪽 열 저장
81+
if(leftmostInRow[ni] == -1 || leftmostInRow[ni] > nj){
82+
leftmostInRow[ni] = nj;
83+
}
84+
//현재 열에서 가장 위쪽 열 저장
85+
if(topmostInCol[nj] == -1 || topmostInCol[nj] > ni){
86+
topmostInCol[nj] = ni;
87+
}
88+
}
89+
}
90+
91+
//도착지에서 BFS
92+
q.offer(new State(N, M, 0));
93+
dist[N][M][1] = 0;
94+
95+
while(!q.isEmpty()){
96+
State cur = q.poll();
97+
98+
for(int d = 0; d < 4; d++){
99+
int ni = cur.i + di[d];
100+
int nj = cur.j + dj[d];
101+
102+
if(OOB(ni, nj)) continue;
103+
if(map[ni][nj] == 1) continue;
104+
if(dist[ni][nj][1] != -1) continue;
105+
106+
dist[ni][nj][1] = cur.cnt + 1;
107+
q.offer(new State(ni, nj, cur.cnt + 1));
108+
}
109+
}
110+
//일단 벽 안뚫고도 만날 수 있으면 값 저장. 앞으로 벽뚫어서 최적될 수도 있음.
111+
if(dist[N][M][0] != -1){
112+
ans = dist[N][M][0];
113+
}
114+
115+
//행 단위로 쭉 보면서 가장 왼쪽 부분에서 오른쪽으로 기술 사용
116+
for(int i = 1; i <= N; i++){
117+
if(leftmostInRow[i] == -1) continue; //애초에 못가는 부분임.
118+
int j = leftmostInRow[i];
119+
120+
int nj = j + 1;
121+
int distance = 0;
122+
int startPoint = dist[i][j][0];
123+
while(!OOB(i, nj)){
124+
distance++;
125+
//이동하면서 이미 가능한 지점이 더욱 가까울 수도 있음.
126+
if(dist[i][nj][0] != -1 && startPoint + distance > dist[i][nj][0]){
127+
distance = 0;
128+
startPoint = dist[i][nj][0];
129+
}
130+
//도착지에서 온 지점과 바로 만나는 경우
131+
if(dist[i][nj][1] != -1){
132+
ans = Math.min(ans, startPoint + distance + dist[i][nj][1]);
133+
}
134+
//오른쪽으로 기술을 사용해서 아래쪽으로 길이 뚤리는 경우
135+
if(!OOB(i+1, nj) && dist[i+1][nj][1] != -1){
136+
ans = Math.min(ans, startPoint + distance + 1 + dist[i+1][nj][1]);
137+
}
138+
//오른쪽으로 기술을 사용해서 위쪽으로 길이 뚤리는 경우
139+
if(!OOB(i-1, nj) && dist[i-1][nj][1] != -1){
140+
ans = Math.min(ans, startPoint + distance + 1 + dist[i-1][nj][1]);
141+
}
142+
nj++;
143+
}
144+
}
145+
146+
//모든 열에 대해서 가장 위쪽 값에서 기술 사용
147+
for(int j = 1; j <= M; j++){
148+
if(topmostInCol[j] == -1) continue;
149+
int i = topmostInCol[j];
150+
151+
int ni = i + 1;
152+
int distance = 0;
153+
int startPoint = dist[i][j][0];
154+
while(!OOB(ni, j)){
155+
distance++;
156+
//이동하면서 이미 가능한 지점이 더욱 가까울 수도 있음.
157+
if(dist[ni][j][0] != -1 && startPoint + distance > dist[ni][j][0]){
158+
distance = 0;
159+
startPoint = dist[ni][j][0];
160+
}
161+
//바로 만나는 경우
162+
if(dist[ni][j][1] != -1){
163+
ans = Math.min(ans, startPoint + distance + dist[ni][j][1]);
164+
}
165+
//아래로 기술 사용해서 오른쪽으로 길이 뚤리는 경우
166+
if(!OOB(ni, j+1) && dist[ni][j+1][1] != -1){
167+
ans = Math.min(ans, startPoint + distance + 1 + dist[ni][j+1][1]);
168+
}
169+
//아래로 기술 사용해서 왼쪽으로 길이 뚫리는 경우
170+
if(!OOB(ni, j-1) && dist[ni][j-1][1] != -1){
171+
ans = Math.min(ans, startPoint + distance + 1 + dist[ni][j-1][1]);
172+
}
173+
ni++;
174+
}
175+
}
176+
}
177+
178+
public static boolean OOB(int i, int j){
179+
return (i<1 || i>N || j<1 || j>M);
180+
}
181+
}
182+
```

0 commit comments

Comments
 (0)