알고리즘/백준

2638_치즈

베리영young 2025. 2. 3. 23:07

사용 알고리즘: bfs

사용 언어: java

 

package week34;

import java.util.*;
public class Main_bj_2638_치즈 {
	static int n, m, map[][], changed;
	static int[] dx = {-1,1,0,0};
	static int[] dy = {0,0,-1,1};

	public static void main(String[] args) {
		init_2638();
		
		int answer = 0;
		while(true) {
			changed = 0;
			
			//0(치즈)에서 사방탐색 후, 주변 -2의 개수 구하기
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					if(map[i][j] == 0) {
						findMinus2(i,j);
						if(map[i][j] >= 2) changed++;
					}
				}
			}
			//0이 어떻게 바뀌었나
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					//1이면, 다시 0으로 바꾸기
					if(map[i][j] == 1) map[i][j] = 0;
					
					//2이상이면, -2로 바꾸기+거기서 bfs돌려서 -2보다 작으면 -2로 바꾸기
					if(map[i][j] >= 2) {
						map[i][j] = -2;
						meltCheese(i, j);
					}
				}
			}
			 
			 
			if(changed == 0) break;
			answer++;
		}
		System.out.println(answer);
	}

	private static void meltCheese(int x, int y) {
		Queue<int[]> q = new ArrayDeque<>();
		q.add(new int[] {x, y});
		
		while(!q.isEmpty()) {
			int[] p = q.poll();
			
			for (int d = 0; d < 4; d++) {
				int nx = p[0] + dx[d];
				int ny = p[1] + dy[d];
				
				if(inMap(nx, ny) && map[nx][ny] < -2) {
					map[nx][ny] = -2;
					q.add(new int[] {nx, ny});
				}
			}
		}
	}

	private static void findMinus2(int x, int y) {
		for (int d = 0; d < 4; d++) {
			int nx = x + dx[d];
			int ny = y + dy[d];
			
			if(inMap(nx, ny) && map[nx][ny] == -2)
				map[x][y]++;
		}
	}

	private static void init_2638() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		map = new int[n][m];
		for (int i = 0; i < map.length; i++) {
			Arrays.fill(map[i], -1);
		}
		
		for (int i = 0; i < map.length; i++) {
			for (int j = 0; j < m; j++) {
				if(sc.nextInt() == 1) 
					map[i][j] = 0;
			}
		}
		
		int hh = -2;
		for (int i = 0; i < map.length; i++) {
			for (int j = 0; j < m; j++) {
				if(map[i][j] == -1) {
					bfs_2638(i,j, hh);
					hh--;
				}
			}
		}
	}

	private static void bfs_2638(int sx, int sy, int hh) {
		Queue<int[]> q = new ArrayDeque<>();
		q.add(new int[] {sx, sy});
		map[sx][sy] = hh;
		
		while(!q.isEmpty()) {
			int[] p = q.poll();
			
			for (int d = 0; d < 4; d++) {
				int nx = p[0] + dx[d];
				int ny = p[1] + dy[d];
				
				if(inMap(nx, ny) && map[nx][ny] == -1) {
					map[nx][ny] = hh;
					q.add(new int[] {nx, ny});
				}
			}
		}
	}

	private static boolean inMap(int nx, int ny) {
		if(nx>=0&&nx<n && ny>=0&&ny<m) return true;
		return false;
	}

}

 

 

메모리를 효율적으로 사용하려고 노력 했다

visit 배열을 포함한 추가적인 배열을 만들지 않고, map[][]으로만 끝내려고 했다!!

 
 
1. 처음 map은 -1로 채우고, 치즈가 있는 부분만 0으로 바꿈
 

2. -1인 부분은 bfs를 돌면서, -2, -3… 등으로 바꿔치기(빈 곳의 덩어리 찾기)

   - 이 과정이 필요한 이유?? ⇒ 문제에서 알 수 있듯, “치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다.”

 
3. 0(치즈)에서, 사방 탐색 후, -2의 개수를 더한다 (이렇게 하면!)
 

4. 0이 어떻게 바뀌었나?

  - 1이면, 다시 0으로 바꾸기

  - 2이상이면(녹는 치즈), -2로 바꾸고, 이 위치를 시작으로 -2보다 작은 곳은 -2로 바꾸기

 

아쉬운 점?

bfs를 하나의 함수로 표현할 수 있지 않을까

'알고리즘 > 백준' 카테고리의 다른 글

5567_결혼식  (0) 2025.02.04
2589_보물섬  (0) 2025.02.04
2295_세 수의 합  (0) 2025.02.02
11404_플로이드 **  (0) 2025.01.22
11726_2×n 타일링  (1) 2025.01.21