빙산


백준 2573: 빙산

문제보기
Alt text

풀이

BFS를 사용하여 빙산을 녹이고,
DFS를 사용하여 빙산이 두 덩어리 이상으로 분리 되는지를 확인

  • dfs(int r, int c, boolean[][] visited)
  • r : 2차원 배열의 행
  • c : 2차원 배열의 열
  • visited : 방문체크 배열

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	static class Node {
		int r, c, year;

		Node(int r, int c, int year) {
			this.r = r;
			this.c = c;
			this.year = year;
		}
	}

	static int[] dr = { -1, 1, 0, 0 };
	static int[] dc = { 0, 0, -1, 1 };
	static int N;
	static int M;
	static int[][] map;

	public static void main(String[] args) throws IOException {
		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];
		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());
			}
		}

		Queue<Node> queue = new LinkedList<>();
		
		int year = 0;
		int cnt = 0;
		
		boolean ch =false;
		
		while (cnt < 2) {	//두 덩어리 이상으로 분리 될때까지
		
			boolean[][] check = new boolean[N][M];
			
			year++;
			
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					//빙산을 다 큐에 담자
					if (map[i][j] != 0)
						queue.add(new Node(i, j, year));	
				}
			}

			while (!queue.isEmpty()) {
				Node node = queue.poll();
				year = node.year;
				for (int d = 0; d < 4; d++) {
					int nr = node.r + dr[d];
					int nc = node.c + dc[d];

					if (nr >= 0 && nc >= 0 && nr < N && nc < M) {
						if (map[nr][nc] == 0 && !check[nr][nc]) {
							map[node.r][node.c] = map[node.r][node.c] - 1;	//빙산을 녹여
							if(map[node.r][node.c]<0)	//빙산을 녹여서 0보다 작아지면
								map[node.r][node.c]=0;	//그 자리는 0으로 만들어줌
							check[node.r][node.c] = true;
						}
					}
				}
			}

			boolean[][] visited = new boolean[N][M];
			cnt=0;
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					if (map[i][j] != 0 && !visited[i][j]) {
						visited[i][j]=true;
						cnt++;
						dfs(i, j, visited);
					}
				}
			}
			
			int zerocnt=0;	//0의 개수를 세기 위한 변수
			for(int i=0; i<N; i++) {
				for(int j=0; j<M; j++) {
					if(map[i][j]==0)
						zerocnt++;
				}
			}
			
			if(zerocnt==N*M)	//배열의 전체가 0이면(빙산이 모두 녹은 것) 끝내기
				break;
		}
		if(cnt<2)
			System.out.println("0");
		else if(cnt>=2)
			System.out.println(year);

	}

	static void dfs(int r, int c, boolean[][] visited) {
		for (int d = 0; d < 4; d++) {
			int nr = r + dr[d];
			int nc = c + dc[d];

			if (nr >= 0 && nc >= 0 && nr < N && nc < M && !visited[nr][nc]&&map[nr][nc]!=0) {
				visited[nr][nc] = true;
				dfs(nr, nc, visited);
			}
		}
	}
}