/ BOJ

BOJ_2573_빙산_JAVA

문제 : 빙산

링크 : BOJ_2573_빙산

접근 방식

년도를 1 증가시킨다.

빙산이 있는 위치를 저장해두고, 사방탐색을 하여 주변의 땅이 물(0)인 개수를 체크해둔다.

그 후 체크한 수만큼 일괄적으로 빙산을 녹인다 (마이너스)

그 다음 BFS를 통해 빙산이 모두 이어져있는지 체크한다.

빙산이 이어져있지 않다면 지금까지의 년도를 출력한다.

만약 빙산이 모두 녹았다면 0을 출력한다.

소스 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ_2573_빙산 {

	static class Node {

		int x;
		int y;

		public Node(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}
	}

	// https://www.acmicpc.net/problem/2573

	static int N, M, arr[][];

	public static void main(String[] args) throws NumberFormatException, IOException {

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		StringTokenizer st = new StringTokenizer(in.readLine(), " ");

		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());

		arr = new int[N][M];



		ArrayList<Node> list = new ArrayList<>();

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(in.readLine(), " ");
			for (int j = 0; j < M; j++) {
				arr[i][j] = Integer.parseInt(st.nextToken());

				if (arr[i][j] != 0) {
					list.add(new Node(i, j));
				}

			}
		}

		int ans = 0;
		while (true) {

			ans++;

			boolean[][] visited = new boolean[N][M];

			int[][] temp = new int[N][M];

			for(int i=list.size()-1;i>=0;i--) {

				Node node = list.get(i);

				int x = node.x;
				int y = node.y;

				for(int d=0;d<4;d++) {

					int dx = node.x + dir[d][0];
					int dy = node.y + dir[d][1];

					if(arr[dx][dy] == 0) {
						temp[x][y]++;
					}

				}				
			}

			for(int i=list.size()-1;i>=0;i--) {
				Node node = list.get(i);

				int x = node.x;
				int y = node.y;

				arr[x][y] = arr[x][y] - temp[x][y];

				if(arr[x][y] <= 0) {
					arr[x][y] = 0;
					list.remove(i);
				}
			}

			// 빙산이 다 녹으면
			if (list.size() == 0) {
				System.out.println(0);
				return;
			}

//			for(int i=0;i<N;i++) {
//				System.out.println(Arrays.toString(arr[i]));
//			}
//			System.out.println("===================");

			// 빙산이 갈라지는 지 체크
			boolean endCheck = false;

			for (int i = 0, n = list.size(); i < n; i++) {

				Node node = list.get(i);

				if (endCheck && !visited[node.x][node.y]) {

					System.out.println(ans);

					return;
				}

				if (!visited[node.x][node.y]) {
					bfs(node, visited);
					endCheck = true;
				}

			}


		}

	}

	static int[][] dir = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };

	private static void bfs(Node node, boolean[][] visited) {

		Queue<Node> queue = new ArrayDeque<>();

		queue.offer(node);

		visited[node.x][node.y] = true;
		while (!queue.isEmpty()) {
			Node temp = queue.poll();

			for (int d = 0; d < 4; d++) {

				int dx =  temp.x + dir[d][0];
				int dy = temp.y + dir[d][1];

				if(!visited[dx][dy] && arr[dx][dy] != 0) {
					visited[dx][dy] = true;
					queue.offer(new Node(dx,dy));
				}
			}
		}

	}

}

얼마 전에 풀었던 치즈를 녹이는 문제와 유사한 면이 있었다. 일괄적으로 빙산을 녹여야 한다는 점을 간과해 몇 차례 틀렸는데, 역시 문제를 꼼꼼히 살펴보고 이해하는 것이 중요하다.