728x90
2146 - 다리 만들기
https://www.acmicpc.net/problem/2146


문제
한 섬과 다른 섬을 잇는 다리 하나만을 만들기로 하였고, 다리를 가장 짧게 하여 돈을 아끼려고 함
NxN 크기의 이차원 평면상에 존재하는 이 나라는 여러 섬으로 이뤄져 있음
섬: 동서남북으로 육지가 붙어있는 덩어리
가장 짧은 다리: 다리가 격자에서 차지하는 칸의 수가 가장 작은 다리
입력
첫 줄: 지도의 크기 N (1 <= N <= 100)
다음 N줄: N개의 숫자 빈칸을 사이에 두고 주어짐 (0: 바다, 1: 육지)
출력: 가장 짧은 다리의 길이
풀이
섬 라벨링
현재 `map`에는 0: 바다, 1: 육지 -> 어느 섬에서 시작했는지 알 수 없음
=> 각 섬을 서로 다른 번호로 변경
- `map[i][j] == 1 && !visited[i][j]`: 섬이고 아직 방문 안했으면 BFS로 연결된 모든 1 같은 번호(`idx`)로 변경
int idx = 2;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 1 && !visited[i][j]) {
labelIsland(i, j, idx);
idx++;
}
}
}
static void labelIsland(int x, int y, int idx) {
Queue<int[]> q = new ArrayDeque<>();
q.offer(new int[]{x, y});
visited[x][y] = true;
map[x][y] = idx;
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int d = 0; d < 4; d++) {
int nx = cur[0] + dx[d];
int ny = cur[1] + dy[d];
if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
if (!visited[nx][ny] && map[nx][ny] == 1) {
visited[nx][ny] = true;
map[nx][ny] = idx;
q.offer(new int[]{nx, ny});
}
}
}
}
다리 길이 구하기
- 한 섬의 모든 칸 BFS 시작점으로 큐에 넣음
- 바다(0)를 지나면 `dist` 증가
- 다른 섬 번호 만나면 종료
static void bfs(int island) {
Queue<int[]> q = new ArrayDeque<>();
boolean[][] visitedBfs = new boolean[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == island) {
q.offer(new int[]{i, j, 0});
visitedBfs[i][j] = true;
}
}
}
while (!q.isEmpty()) {
int[] cur = q.poll();
int x = cur[0];
int y = cur[1];
int dist = cur[2];
if (dist >= ans) return;
for (int d = 0; d < 4; d++) {
int nx = x + dx[d];
int ny = y + dy[d];
if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
if (visitedBfs[nx][ny]) continue;
if (map[nx][ny] != 0 && map[nx][ny] != island) {
ans = Math.min(ans, dist);
return;
}
if (map[nx][ny] == 0) {
visitedBfs[nx][ny] = true;
q.offer(new int[]{nx, ny, dist + 1});
}
}
}
}
코드
import java.io.*;
import java.util.*;
// 다리 만들기
public class boj_2146 {
static int N;
static int[][] map;
static boolean[][] visited;
static int ans = Integer.MAX_VALUE;
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
static void labelIsland(int x, int y, int idx) {
Queue<int[]> q = new ArrayDeque<>();
q.offer(new int[]{x, y});
visited[x][y] = true;
map[x][y] = idx;
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int d = 0; d < 4; d++) {
int nx = cur[0] + dx[d];
int ny = cur[1] + dy[d];
if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
if (!visited[nx][ny] && map[nx][ny] == 1) {
visited[nx][ny] = true;
map[nx][ny] = idx;
q.offer(new int[]{nx, ny});
}
}
}
}
static void bfs(int island) {
Queue<int[]> q = new ArrayDeque<>();
boolean[][] visitedBfs = new boolean[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == island) {
q.offer(new int[]{i, j, 0});
visitedBfs[i][j] = true;
}
}
}
while (!q.isEmpty()) {
int[] cur = q.poll();
int x = cur[0];
int y = cur[1];
int dist = cur[2];
if (dist >= ans) return;
for (int d = 0; d < 4; d++) {
int nx = x + dx[d];
int ny = y + dy[d];
if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
if (visitedBfs[nx][ny]) continue;
if (map[nx][ny] != 0 && map[nx][ny] != island) {
ans = Math.min(ans, dist);
return;
}
if (map[nx][ny] == 0) {
visitedBfs[nx][ny] = true;
q.offer(new int[]{nx, ny, dist + 1});
}
}
}
}
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];
visited = new boolean[N][N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
int idx = 2;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 1 && !visited[i][j]) {
labelIsland(i, j, idx);
idx++;
}
}
}
for (int i = 2; i < idx; i++) bfs(i);
System.out.println(ans);
}
}728x90
반응형
'✏️ > BOJ' 카테고리의 다른 글
| [BOJ/Segment Tree] 백준 11505 - 구간 곱 구하기 (Java) (0) | 2025.12.24 |
|---|---|
| [BOJ/DP] 백준 11066 - 파일 합치기 (Java) (0) | 2025.12.22 |
| [BOJ/DP] 백준 11049 - 행렬 곱셈 순서 (Java) (0) | 2025.12.22 |
| [BOJ/Segment Tree] 백준 2042 - 구간 합 구하기 / 10999 - 구간 합 구하기 2 (Java) (0) | 2025.12.20 |
| [BOJ/Greedy] 백준 1700 - 멀티탭 스케줄링 (Java) (0) | 2025.12.16 |