백준공부/java
[백준] 3197번 백조의 호수 (platinum 5
gomduri43
2024. 3. 27. 17:00
import java.io.*;
import java.util.*;
class Point{
int xy;
int v;
public Point(int xy, int v){
this.xy=xy;
this.v=v;
}
}
public class Main{
static int[] numx={-1,1,0,0};
static int[] numy={0,0,-1,1};
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st=new StringTokenizer(br.readLine());
int n=Integer.valueOf(st.nextToken());
int m=Integer.valueOf(st.nextToken());
PriorityQueue<Point> que=new PriorityQueue<>(new Comparator<Point>(){
public int compare(Point o1, Point o2){
return o1.v-o2.v;
}
});
Queue<Point> que2=new LinkedList<>();
ArrayList<Point> bird=new ArrayList<>();
int[][] time=new int[n+1][m+1];
for(int i=1; i<=n; i++){
String a=br.readLine();
for(int j=1; j<=m; j++){
char c=a.charAt(j-1);
if(c=='X'){
time[i][j]=-1;
}
//새의 위치 저장.
//여기서 중요한점. 새가 앉은 곳은 얼음이 아니었다......(메모리 초과이후 틀린 이유)
else if(c=='L'){
bird.add(new Point(j*10000+i,0));
que2.offer(new Point(j*10000+i,0));
}
//물의 위치를 que2에 넣기.
//그리고 que2에서 bfs를 진행하면서, 얼음들을 녹이면
//결국 얼음들은 물에서 그 얼음까지 도달한 시간이 얼음이 그날 만큼 지나야
//녹는다는 의미이다.
else{
que2.offer(new Point(j*10000+i,0));
}
}
}
//빙판 싹 녹이기.
//빙판이 녹는데 걸린 시간을 저장한다.
while(!que2.isEmpty()){
Point temp=que2.poll();
for(int i=0; i<4; i++){
int tx=temp.xy/10000+numx[i];
int ty=temp.xy%10000+numy[i];
if(tx<1 || tx>m || ty<1 || ty>n || time[ty][tx]!=-1){
continue;
}
time[ty][tx]=temp.v+1;
que2.offer(new Point(tx*10000+ty, temp.v+1));
}
}
que.clear();
boolean[][] visit=new boolean[n+1][m+1];
visit[bird.get(0).xy%10000][bird.get(0).xy/10000]=true;
que.offer(bird.get(0));
//하나의 백조를 넣고, 다른 백조까지 도달할 때까지, bfs를 진행한다.
//이때 위에서는 물에서부터 진행으로, 어떤 얼음에 도달한 물은 가장 빨리 도착한 것이다.
//하지만, 여기선 map에 다양한 시간이 걸려서 녹은 얼음들이 존재하므로,
//그냥 bfs를 돌린다고 최선의 선택이 아니다. 따라서, pq를 통해서,
//해당지점까지 적게 걸린 케이스를 우선으로 뽑아내서 bfs를 진행한다.
while(!que.isEmpty()){
Point temp=que.poll();
int tempx=temp.xy/10000;
int tempy=temp.xy%10000;
if(tempx==bird.get(1).xy/10000 && tempy==bird.get(1).xy%10000){
bw.write(temp.v+"");
break;
}
for(int i=0; i<4; i++){
int tx=tempx+numx[i];
int ty=tempy+numy[i];
if(tx<1 || tx>m || ty<1 || ty>n || visit[ty][tx]){
continue;
}
visit[ty][tx]=true;
int day= temp.v > time[ty][tx] ? temp.v : time[ty][tx];
que.offer(new Point(tx*10000+ty, day));
}
}
bw.flush();
}
}