문제 링크 : https://www.acmicpc.net/problem/2573
2573번: 빙산
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을
www.acmicpc.net
문제
지구 온난화로 인하여 북극의 빙산이 녹고 있다. 빙산을 그림 1과 같이 2차원 배열에 표시한다고 하자. 빙산의 각 부분별 높이 정보는 배열의 각 칸에 양의 정수로 저장된다. 빙산 이외의 바다에 해당되는 칸에는 0이 저장된다. 그림 1에서 빈칸은 모두 0으로 채워져 있다고 생각한다.
빙산의 높이는 바닷물에 많이 접해있는 부분에서 더 빨리 줄어들기 때문에, 배열에서 빙산의 각 부분에 해당되는 칸에 있는 높이는 일년마다 그 칸에 동서남북 네 방향으로 붙어있는 0이 저장된 칸의 개수만큼 줄어든다. 단, 각 칸에 저장된 높이는 0보다 더 줄어들지 않는다. 바닷물은 호수처럼 빙산에 둘러싸여 있을 수도 있다. 따라서 그림 1의 빙산은 일년후에 그림 2와 같이 변형된다.
그림 3은 그림 1의 빙산이 2년 후에 변한 모습을 보여준다. 2차원 배열에서 동서남북 방향으로 붙어있는 칸들은 서로 연결되어 있다고 말한다. 따라서 그림 2의 빙산은 한 덩어리이지만, 그림 3의 빙산은 세 덩어리로 분리되어 있다.
한 덩어리의 빙산이 주어질 때, 이 빙산이 두 덩어리 이상으로 분리되는 최초의 시간(년)을 구하는 프로그램을 작성하시오. 그림 1의 빙산에 대해서는 2가 답이다. 만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다.
입력
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 나타내는 M개의 정수가 한 개의 빈 칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0 이상 10 이하이다. 배열에서 빙산이 차지하는 칸의 개수, 즉, 1 이상의 정수가 들어가는 칸의 개수는 10,000 개 이하이다. 배열의 첫 번째 행과 열, 마지막 행과 열에는 항상 0으로 채워진다.
출력
첫 줄에 빙산이 분리되는 최초의 시간(년)을 출력한다. 만일 빙산이 다 녹을 때까지 분리되지 않으면 0을 출력한다.
예제 입력 1
5 7
0 0 0 0 0 0 0
0 2 4 5 3 0 0
0 3 0 2 5 2 0
0 7 6 2 4 0 0
0 0 0 0 0 0 0
예제 출력 1
2
문제 풀이
시뮬레이션 문제와 같이 접근 하였다.
한 턴 마다 2차원 array 객체를 생성하여 인접해 있는 바다의 크기 만큼 빙산의 값을 감소 시켜 저장해두고
턴을 마칠 때 현재의 빙산의 상황을 갱신해주는 방향으로 문제를 풀었다.(덕분에 메모리 사용량이 너무 많다)
현재의 빙산의 상황을 갱신한 뒤 bfs로 분리된 섬의 개수를 계산한다.
만약 빙산이 여전히 하나라면 다음 턴을 진행하고 2개로 갈라졌다면 반복문을 종료하고 현재까지 걸린 시간을 출력하였다.
코드
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_BJ_2573_빙산 {
static int N, M;
static int[][] map;
static int[][] D = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
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());
}
}
int ans = 0;
while (true) {
ans++;
thaw();
if (checkSplit() == 0) {
ans = 0;
break;
} else if (checkSplit() == 2) {
break;
}
}
System.out.println(ans);
}
static void thaw() {
int[][] temp = new int[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 0)
continue;
// 일단 해당 지점 얼음의 크기를 새로운 배열에 저장
temp[i][j] = map[i][j];
for (int d = 0; d < 4; d++) {
int nx = i + D[d][0];
int ny = j + D[d][1];
if (nx < 0 || ny < 0 || nx >= N || ny >= M)
continue;
// 만약 상하좌우에 물이 있다면? 해당 값을 -1 해
if (map[nx][ny] == 0) {
temp[i][j]--;
}
}
// 다 돌았을 때 기존 빙하의 크기가 주변 물에 닿은 부분보다 값이 작아 -가 되었다면 0으로 돌려줌
if (temp[i][j] < 0)
temp[i][j] = 0;
}
}
// 기존의 배열을 새로 업데이트 한 값으로 바꿔줌
map = temp;
}
// 2차원 배열 전체의 값을 모두 더하고 한 지점에서 bfs로 탐색하면서 더한 값과 비교하여
// 동일한 값이 나오면 하나의 섬(return 1) 그렇지 않으면 두개 이상의 섬(return 2)으로 갈라졌다고 판단한다.
// 혹시 total 값이 0이라면 전부 녹아 빙산이 없어진 것이므로 0을 반환하여 알려준다.
static int checkSplit() {
boolean[][] visited = new boolean[N][M];
int total = 0;
int init_x = -1;
int init_y = -1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (init_x == -1 && init_y == -1 && map[i][j] != 0) {
init_x = i;
init_y = j;
}
total += map[i][j];
}
}
if (total == 0)
return 0;
int cnt = 0;
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[] { init_x, init_y });
visited[init_x][init_y] = true;
cnt += map[init_x][init_y];
while (!queue.isEmpty()) {
int[] now = queue.poll();
for (int d = 0; d < 4; d++) {
int nx = now[0] + D[d][0];
int ny = now[1] + D[d][1];
if (nx < 0 || ny < 0 || nx >= N || ny >= M || visited[nx][ny] || map[nx][ny] == 0)
continue;
visited[nx][ny] = true;
queue.offer(new int[] { nx, ny });
cnt += map[nx][ny];
}
}
if (total == cnt) {
return 1;
} else {
return 2;
}
}
}
'JAVA > 알고리즘 문제풀이' 카테고리의 다른 글
[JAVA] boj 1106 호텔 (1) | 2021.12.15 |
---|---|
[JAVA] boj 11054 가장 긴 바이토닉 부분 수열 (0) | 2021.12.13 |
[JAVA] boj 2610 회의준비 (0) | 2021.12.13 |
[JAVA] boj 1082 방 번호 (0) | 2021.12.12 |
[JAVA] boj 14226 이모티콘 (0) | 2021.12.12 |