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