1. 각각의 섬에 번호를 붙인다.
2. 각 섬에서 bfs를 수행해 다른 섬으로 가는 다리를 구해서 짧은 것으로 업데이트한다.
import java.io.*;
import java.util.*;
public class Main {
// 지도의 크기
static int N;
// 섬에 붙일 번호
// 0은 바다, 1은 섬이니 2부터
static int landNum = 2;
static int[][] map;
static boolean[][] visit;
// 가장 짧은 다리의 길이
static int answer = Integer.MAX_VALUE;
// 방향 배열
static int[] dx = {0,0,-1,1};
static int[] dy = {1,-1,0,0};
static class Node{
int num;
int x;
int y;
Node(int num, int x, int y){
this.num=num;
this.x=x;
this.y=y;
}
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
map = new int[N][N];
visit = new boolean[N][N];
StringTokenizer st;
// 지도 만들기
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine()," ");
for(int j=0;j<N;j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
// 육지라면 그 육지가 몇번 섬인지 표시
for(int i=0;i<N;i++) {
for(int j=0;j<N;j++) {
if(map[i][j]==1) {
markLand(i,j);
}
}
}
// 번호가 붙여진 섬에 대해서 bfs를 수행해 다리를 찾음
for(int i=0;i<N;i++) {
for(int j=0;j<N;j++) {
if(map[i][j]>=2) {
// 방문했던 걸 초기화
visit = new boolean[N][N];
bfs(i,j);
}
}
}
System.out.println(answer);
}
static void bfs(int x, int y) {
// 큐 생성후 노드 추가
Queue<Node> queue = new LinkedList<>();
queue.add(new Node(0, x, y));
// 그 육지가 몇 번 섬인지 num에 저장
int num = map[x][y];
visit[x][y] = true;
// 큐가 빌 때까지 반복
while(!queue.isEmpty()) {
Node node = queue.poll();
int px = node.x;
int py = node.y;
for(int i=0;i<4;i++) {
int nx = px+dx[i];
int ny = py+dy[i];
// 지도의 범위 안에서
if(nx>=0&&ny>=0&&nx<N&&ny<N) {
// 아직 방문하지 않았고
// 바다이거나 다른 섬이라면
if(!visit[nx][ny]&&map[nx][ny]!=num) {
visit[nx][ny] = true;
// 바다라면 다리를 놓을 수 있으므로
// 다리의 길이를 1 증가 시킴
if(map[nx][ny]==0) {
queue.add(new Node(node.num+1,nx,ny));
}
// 다른 섬에 도착했다면 == 다리가 다 만들어졌다면
else {
// 기존의 가장 짧은 다리의 길이와
// 새로운 다리의 중 짧은 것으로
// answer 업데이트
answer = Math.min(answer, node.num);
}
}
}
}
}
}
static void markLand(int x, int y) {
// 큐 생성
Queue<Node> queue = new LinkedList<>();
queue.offer(new Node(0, x, y));
// 방문했다고 표시 후 지도에 섬의 번호 기입
visit[x][y] = true;
map[x][y] = landNum;
// 큐가 빌 때까지 반복 == 하나의 섬을 다 탐색할 때까지 반복
while(!queue.isEmpty()) {
// 큐에서 노드 하나를 뽑아냄
Node node = queue.poll();
int qx = node.x;
int qy = node.y;
for(int k=0;k<4;k++) {
int nx = qx+dx[k];
int ny = qy+dy[k];
if(nx>=0&&ny>=0&&nx<N&&ny<N) {
// 아직 방문하지 않은 인접한 땅이 있다면
if(!visit[nx][ny]&&map[nx][ny]==1) {
// 그 땅을 다시 큐에 넣고, 번호 표시 후 방문했다고 체크
queue.add(new Node(0,nx,ny));
visit[nx][ny] = true;
map[nx][ny] = landNum;
}
}
}
}
// while 문이 끝났다는 건 하나의 섬을 다 돌았다는 뜻이므로
// 섬의 번호를 증가시킴
landNum++;
}
}
'[BOJ] - JAVA' 카테고리의 다른 글
[백준] 11725 : 트리의 부모 찾기 JAVA 풀이 (0) | 2022.10.20 |
---|---|
[백준] 1991 : 트리 순회 JAVA 풀이 (0) | 2022.10.20 |
[백준] 2178 : 미로 탐색 JAVA 풀이 (1) | 2022.10.14 |
[백준] 7569 : 토마토 JAVA 풀이 (1) | 2022.10.14 |
[백준] 7576 : 토마토 JAVA 풀이 (0) | 2022.10.14 |