Live Today
[백준] 2573. 빙산 (Java) 본문
반응형
https://www.acmicpc.net/problem/2573
2573번: 빙산
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을
www.acmicpc.net
🌙 문제 조건을 세세히 읽고 풀자.
"만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다."
→ 이 조건을 인지 못해서 틀렸었다.
✔️ 풀이방법
- 매년 빙하가 녹는다.
- 여기서 빙하 녹는 것 처리할 때 바로바로 2차원배열에 바뀐 값을 반영하면 안됨.
- 그래서 모든 2차원 배열 빙하 녹는 것 처리한 다음 마지막에 한 번에 2차원배열 값 바꿔야 함.
- 빙하 덩어리 체크 → bfs로 체크
- 빙하가 전부 다 녹을 때까지 분리되지 않는지 체크 → while문의 기저조건으로 처리함
✅ 코드
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 int N,M,result;
static int[][] board;
static int[] dx = {-1,1,0,0};
static int[] dy = {0,0,-1,1};
// 한 덩어리의 빙산이 주어질 때, 이 빙산이 두 덩어리 이상으로 분리되는 최초의 시간(년)을 구하는 프로그램을 작성
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
board = new int[N][M];
boolean flag = false;
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<M;j++) {
board[i][j] = Integer.parseInt(st.nextToken());
if(!flag && board[i][j] > 0) {
flag = true;
}
}
} // input end
result = 0;
solve();
System.out.println(result);
}
private static void solve() {
// 배열에서 빙산의 각 부분에 해당되는 칸에 있는 높이는 일년마다 그 칸에 동서남북 네 방향으로 붙어있는 0이 저장된 칸의 개수만큼 줄어든다.
// 단, 각 칸에 저장된 높이는 0보다 더 줄어들지 않는다.
// 바닷물은 호수처럼 빙산에 둘러싸여 있을 수도 있다.
while(!checkStatus()) {
// 만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다.
boolean flag = true;
outer:for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
if(board[i][j] != 0) {
flag = false;
break outer;
}
}
}
if(flag) {
result = 0;
break;
}
int[][] copy = new int[N][M];
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
if(board[i][j] > 0) {
int cnt = 0;
for(int d=0;d<4;d++) {
int nx = i + dx[d];
int ny = j + dy[d];
if(isValid(nx,ny) && board[nx][ny] == 0) cnt++;
}
int num = board[i][j] - cnt;
if(num < 0) num = 0;
copy[i][j] = num;
}
}
}
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
board[i][j] = copy[i][j];
}
}
result++;
}
}
private static boolean checkStatus() {
int[][] boardArea = new int[N][M]; // 현재 board의 덩어리 확인하기 위한 변수
int cnt = 1;
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
if(board[i][j] > 0 && boardArea[i][j] == 0) {
bfs(i,j,boardArea,cnt);
cnt++;
}
}
}
if(cnt > 2) return true;
return false;
}
private static void bfs(int kx, int ky, int[][] boardArea, int cnt) {
Queue<int[]> q = new LinkedList<>();
q.add(new int[] {kx,ky});
boardArea[kx][ky] = cnt;
while(!q.isEmpty()) {
int[] temp = q.poll();
int x = temp[0];
int y = temp[1];
for(int d=0;d<4;d++) {
int nx = x + dx[d];
int ny = y + dy[d];
if(!isValid(nx,ny) || boardArea[nx][ny] > 0) continue;
if(board[nx][ny] > 0) {
q.add(new int[] {nx,ny});
boardArea[nx][ny] = cnt;
}
}
}
}
private static boolean isValid(int r, int c) {
if(r<0 || c<0 || r>=N || c>=M) return false;
return true;
}
}
'알고리즘 > 백준 문제풀이' 카테고리의 다른 글
[백준] 17135. 캐슬디펜스 (Java) (0) | 2023.06.17 |
---|---|
[백준] 1302. 베스트셀러 (Java) (0) | 2023.06.15 |
[백준] 19237. 어른 상어 (Java) (0) | 2023.03.03 |
[백준] 1181. 단어 정렬 (Java) (0) | 2023.02.12 |
[백준] 2902. KMP는 왜 KMP일까? (Java) (0) | 2023.02.12 |