728x90
문제
접근 방식
1이 끊어지지 않고 최대로 이어진 곳들을 하나의 대륙이라고 볼 수 있고
각 대륙들을 서로 잇는 다리의 길이들을 구해야 한다.
일단 각 대륙들을 구분하면서 각 대륙의 외곽 지역을 큐들에 집어넣었는데
대륙의 외곽 지역은 바다와 맞닿아 있는 땅이라고 볼 수 있다.
외곽 지역을 모두 찾은 후에는 외곽을 순회하면서
바다만 찾아서 탐색을 하면서 다른 대륙을 마주친 경우
현재까지 이동한 거리를 이전의 다리 길이와 비교하여
더 작은 경우에는 값을 바꿔주었다.
풀이 자체는 쉽게 떠올렸는데 코드로 구현하고 보니 엄청 길어진...
풀이
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int[] dx = {-1, 1, 0, 0};
int[] dy = {0, 0, -1, 1};
int n = Integer.parseInt(br.readLine());
int[][] maps = new int[n][n];
boolean[][] isVisited = new boolean[n][n];
boolean[][] isWall = new boolean[n][n];
int count = 0;
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
int num = Integer.parseInt(st.nextToken());
maps[i][j] = num;
count = Math.max(count, num);
}
}
int area = 1;
Queue<Continent> continents;
Queue<Continent> walls = new LinkedList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!isVisited[i][j] && maps[i][j] == 1) {
continents = new LinkedList<>();
continents.offer(new Continent(i, j));
isVisited[i][j] = true;
maps[i][j] = area;
while (!continents.isEmpty()) {
Continent cur = continents.poll();
for (int dir = 0; dir < 4; dir++) {
int x = cur.x + dx[dir];
int y = cur.y + dy[dir];
if (x < 0 || x >= n || y < 0 || y >= n) continue;
if (isVisited[x][y]) continue;
if (maps[x][y] == 0) {
if (!isWall[cur.x][cur.y]) {
isWall[cur.x][cur.y] = true;
walls.offer(cur);
}
continue;
}
isVisited[x][y] = true;
maps[x][y] = area;
continents.offer(new Continent(x, y));
}
}
area++;
}
}
}
int distance = Integer.MAX_VALUE;
Queue<Continent> queue;
while (!walls.isEmpty()) {
Continent wall = walls.poll();
int continent = maps[wall.x][wall.y];
queue = new LinkedList<>();
isVisited = new boolean[n][n];
wall.dist = 0;
queue.offer(wall);
isVisited[wall.x][wall.y] = true;
while (!queue.isEmpty()) {
Continent cur = queue.poll();
for (int dir = 0; dir < 4; dir++) {
int x = cur.x + dx[dir];
int y = cur.y + dy[dir];
if (x < 0 || x >= n || y < 0 || y >= n) continue;
int next = maps[x][y];
if (next == continent || isVisited[x][y]) continue;
if (next != 0) {
distance = Math.min(distance, cur.dist);
continue;
}
if (cur.dist >= distance) {
isVisited[x][y] = true;
continue;
}
isVisited[x][y] = true;
queue.offer(new Continent(x, y, cur.dist + 1));
}
}
}
System.out.println(distance);
}
private static class Continent {
int x;
int y;
int dist;
public Continent(int x, int y) {
this.x = x;
this.y = y;
}
public Continent(int x, int y, int dist) {
this.x = x;
this.y = y;
this.dist = dist;
}
}
}
'Java > Algorithms' 카테고리의 다른 글
[백준] 1600번 : 말이 되고픈 원숭이 (1) | 2023.11.15 |
---|---|
[백준] 13549번 : 숨바꼭질 3 (1) | 2023.11.14 |
[백준] 2573번 : 빙산 (1) | 2023.11.12 |
[백준] 9466번 : 텀 프로젝트 (1) | 2023.11.10 |
[백준] 2206번 : 벽 부수고 이동하기 (0) | 2023.11.08 |