알고리즘 공부/문제 풀이
[JAVA] 백준 17472 다리 만들기2
valid_ming
2021. 9. 17. 10:59
https://www.acmicpc.net/problem/17472
17472번: 다리 만들기 2
첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 N개의 줄에 지도의 정보가 주어진다. 각 줄은 M개의 수로 이루어져 있으며, 수는 0 또는 1이다. 0은 바다, 1은 땅을 의미한다.
www.acmicpc.net
문제의 설명은 링크와 문제 분석을 참고해주세요

풀이
해결 전략은 문제를 풀며 적은 내용으로 실제 작성한 코드와 상이할 수 있습니다.
변경된 부분은 왜 변경했는지 풀이 후기에 적어 놓았으니 참고 바랍니다!


코드
import java.util.*;
import java.io.*;
public class Main {
static int N, M;
static int[][] map;
static int[][] d = {{-1, 1, 0, 0}, {0, 0, -1, 1}};
static boolean[][] visit;
public static void main(String[] args) throws Exception {
// 입력
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
visit = new boolean[N][M];
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<M;j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
//1. 섬에 번호 붙이기
int num = 1;
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
if(map[i][j]==0 || visit[i][j]) continue;
dfs(i, j, num);
num++;
}
}
//2. dist 배열 만들기
int[][] dist = new int[num][num];
for(int i=0;i<num;i++) {
for(int j=0;j<num;j++) dist[i][j] = 100;
}
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
if(map[i][j]==0) continue;
int cur = map[i][j];
for(int k=0;k<4;k++) {
int nr = i + d[0][k];
int nc = j + d[1][k];
int cnt = 0;
while(inMap(nr, nc) && map[nr][nc]==0) {
nr += d[0][k];
nc += d[1][k];
cnt ++;
}
if(cnt<2) cnt = 100;
if(inMap(nr, nc) && map[nr][nc]!=0 && map[nr][nc]!= cur) {
dist[cur][map[nr][nc]] = Math.min(cnt, dist[cur][map[nr][nc]]);
}
}
}
}
//3. 프림 알고리즘
int answer = 0;
boolean[] include = new boolean[num];
int cnt = 0;
PriorityQueue<Integer[]> pq = new PriorityQueue<>(
(Integer[] a, Integer[] b) -> a[1]-b[1]
);
pq.add(new Integer[] {1, 0});
while(!pq.isEmpty()) {
Integer[] edge = pq.poll();
int cur = edge[0];
if(include[cur]) continue;
include[cur] = true;
answer += edge[1];
cnt++;
for(int i=1;i<num;i++) {
if(!include[i] && i!=cur && dist[cur][i]!=100) {
pq.add(new Integer[] {i, dist[cur][i]});
}
}
}
if(cnt==num-1) System.out.println(answer);
else System.out.println(-1);
}
public static void dfs(int row, int col, int num) {
visit[row][col] = true;
map[row][col] = num;
for(int i=0;i<4;i++) {
int nr = row + d[0][i];
int nc = col + d[1][i];
if(inMap(nr, nc) && !visit[nr][nc] && map[nr][nc]==1) {
dfs(nr, nc, num);
}
}
}
public static boolean inMap(int row, int col) {
if(0<=row && row<N && 0<=col && col<M) return true;
else return false;
}
}