티스토리 뷰

www.acmicpc.net/problem/17472

 

17472번: 다리 만들기 2

첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 N개의 줄에 지도의 정보가 주어진다. 각 줄은 M개의 수로 이루어져 있으며, 수는 0 또는 1이다. 0은 바다, 1은 땅을 의미한다.

www.acmicpc.net

 

 

import java.util.*;
import java.io.*;
// 210424

public class Main_BJ_17472_다리만들기2 {
	static int N, M;
	static int[][] map;
	static StringBuilder sb;
	static int[][] adjMatrix;
	static int[] dr = {-1, 0, 1, 0};
	static int[] dc = {0, -1, 0, 1};
	static boolean[][] v;
	
	public static void main(String[] args) throws Exception {
		//System.setIn(new FileInputStream("res/input_17472_다리만들기2.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		sb = new StringBuilder();
		StringTokenizer st;
		
		st = new StringTokenizer(br.readLine());
		N = stoi(st.nextToken());
		M = stoi(st.nextToken());
		map = new int[N][M];
		
		for(int i=0; i<N; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<M; j++) {
				map[i][j] = stoi(st.nextToken());
			}
		}
		
		solve();
		
		System.out.println(sb.toString());
		br.close();
	}
	
	static void solve() {
		// 1. 섬 번호 붙이기
		int islandNum = 0;
		v = new boolean[N][M]; 
		for(int i=0; i<N; i++) {
			for(int j=0; j<M; j++) {
				if(map[i][j]!=0 && !v[i][j]) {
					bfs(i, j, ++islandNum);
				}
			}
		}

		adjMatrix = new int[islandNum+1][islandNum+1]; // 섬은 1부터 시작
		// 인접행렬 최대값으로 초기화
		for(int i=0; i<=islandNum; i++) {
			Arrays.fill(adjMatrix[i], Integer.MAX_VALUE);
		}
		
		// 2. 섬 건설 (dfs)
		for(int i=0; i<N; i++) {
			for(int j=0; j<M; j++) {
				if(map[i][j]!=0) {
					for(int d=0; d<4; d++) {
						int nr = i + dr[d];
						int nc = j + dc[d];
						if(nr<0 || nr>=N || nc<0 || nc>=M) continue;
						if(map[nr][nc]==0) {
							// 섬 건설 시도
							build(nr, nc, d, map[i][j], 1);
						}
						
					}
					
				}
			}
		}
		
		// 3. 거리 세기 (Prim 알고리즘)
		sb.append(prim(islandNum));
	}
	
	// 1.
	static void bfs(int r, int c, int islandNum) {
		map[r][c] = islandNum;
		v[r][c] = true;
		Queue<int[]> q = new ArrayDeque<int[]>();
		q.offer(new int[] {r, c});
		
		while(!q.isEmpty()) {
			int[] cur = q.poll();
			
			for(int d=0; d<4; d++) {
				int nr = cur[0] + dr[d];
				int nc = cur[1] + dc[d];
				
				if(nr<0 || nr>=N || nc<0 || nc>=M || map[nr][nc]==0 || v[nr][nc]) continue;
				v[nr][nc] = true;
				map[nr][nc] = islandNum;
				q.offer(new int[] {nr, nc});
			}
		}
	}
	
	// 2.
	static void build(int r, int c, int dir, int islandNum, int len) {
		int nr = r + dr[dir];
		int nc = c + dc[dir];
		
		// 경계에 막혀있는 곳은 건설 불가
		if(nr<0 || nr>=N || nc<0 || nc>=M) return;
		
		// 길이 1인 곳은 건설 불가
		if(len==1 && map[nr][nc]!=0) return;
		
		if(map[nr][nc]==0) build(nr, nc, dir, islandNum, len+1);
		
		if(map[nr][nc]!=0 && map[nr][nc]!=islandNum) {
			// 건설 시도
			int from = islandNum;
			int to = map[nr][nc];
			
			if(adjMatrix[from][to] > len) {
				adjMatrix[from][to] = len;
				adjMatrix[to][from] = len;
			}
		}
	}
	
	// 3. 거리 세기
	static int prim(int islandNum) {
		boolean[] pv = new boolean[islandNum+1]; // 정점방문 여부 체크
		int[] minEdge = new int[islandNum+1]; // 신장트리에 연결된 최소 간선 비용
		int totalWeight = 0; // 최종 가중치의 합
		Arrays.fill(minEdge, Integer.MAX_VALUE);
		minEdge[1] = 0; // 임의의 정점 1을 시작 정점으로 처리
		
		for(int c=1; c<=islandNum; c++) {
			int min = Integer.MAX_VALUE;
			int minVertext = 0;
			
			// 신장트리에 연결되지 않은 정점 중 minEdge 비용이 최소인 정점
			for(int i=1; i<=islandNum; i++) {
				if(!pv[i] && min > minEdge[i]) {
					min = minEdge[i];
					minVertext = i;
				}
			}
			
			totalWeight += min;
			pv[minVertext] = true;
			
			// 선택 정점에서부터의 최소 거리를 찾아 비용 update
			for(int i=1; i<=islandNum; i++) {
				if(!pv[i] && adjMatrix[minVertext][i]!=0 
						&& minEdge[i] > adjMatrix[minVertext][i]) {
					minEdge[i] = adjMatrix[minVertext][i];
				}
			}
			
		} // for
		
		for(int i=1; i<=islandNum; i++) {
			if(minEdge[i]==Integer.MAX_VALUE) 
				return -1; // 갈 수 없는 경우
		}
		
		return totalWeight;
	}

	static int stoi(String str) {
		return Integer.parseInt(str);
	}
}

'코딩테스트 > 백준' 카테고리의 다른 글

[BJ] 1238. 파티  (0) 2021.06.25
[BJ] 1932. 정수 삼각형  (0) 2021.06.06
[BJ] 20057. 마법사 상어와 토네이도  (0) 2021.04.24
[BJ] 17142. 연구소 3  (0) 2021.04.23
[BJ] 17143. 낚시왕  (0) 2021.04.23
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함