-
14502 - 연구소Baekjoon 2022. 12. 28. 17:28
1. 서론
4방향 bfs 문제이다. N, M의 범위가 8이고, 벽의 개수가 3으로 정해져 있어 어렵지 않게 풀 수 있었다.
완전탐색을해도 재귀의 깊이가 3밖에 되지 않으므로, 벽/바이러스가 하나도 없다고 생각하고 벽을 3개 세운다고 하더라도 64C3번의 연산만 하면 된다.(=41664회)
2. 풀이
문제에서 중요하게 생각해야될것은 하나이다.
벽을 세운 후, 바이러스가 퍼지는것을 구현하고 안전영역의 개수를 구해야 한다. 이 때, 바이러스가 퍼지는것은 경우의 수 때 마다 다르므로 기존맵을 복사한 후 각각 사용해야 한다.
-> 바이러스가 퍼질 때는 기존 맵에 3개의 벽을 세운 후이다. 따라서 재귀 깊이 3에 도달했을 때, 기존 맵을 복사해 새로운 맵을 만든 후 해당 맵에서 bfs를 통해 바이러스가 퍼져나가는것을 시뮬레이션하면 된다.
BFS 부분 코드
public static void bfs(int x, int depth) { if (depth == 3) { // 재귀 깊이가 3일 때. 벽을 다 세웠으므로, 바이러스가 퍼져나가는것을 dfs를 통해 시뮬레이션한다. int result = init_safe; int[][] sub_map = new int[map.length][map[0].length]; for (int i = 0; i < sub_map.length; i++) sub_map[i] = map[i].clone(); // 기존 맵을 복사해 시뮬레이션용 맵을 새로 만든다. Queue<Cord> queue = new LinkedList<>(virus); while (!queue.isEmpty()) { Cord elem = queue.poll(); for (int i = 0; i < 4; i++) { int nx = dx[i] + elem.x; int ny = dy[i] + elem.y; if (nx >= 0 && nx < map.length && ny >= 0 && ny < map[0].length && sub_map[nx][ny] == 0) { queue.add(new Cord(nx, ny)); sub_map[nx][ny] = 2; result--; } } } if (result > answer) answer = result; } else { for (int i = x; i < map.length; i++) { for (int j = 0; j < map[0].length; j++) { if (map[i][j] == 0) { map[i][j] = 1; bfs(i, depth + 1); map[i][j] = 0; } } } } }
이 외에는 main에서 입력을 받고, 초깃값들을 세팅하는것 뿐이다.
전체 코드
import java.util.*; public class P_14502 { static ArrayList<Cord> virus; static int[][] map; static int[] dx = {0, 0, 1, -1}; static int[] dy = {1, -1, 0 , 0}; static int answer; static int init_safe; static class Cord { int x; int y; Cord(int x, int y) { this.x = x; this.y = y; } } public static void bfs(int x, int depth) { if (depth == 3) { // 재귀 깊이가 3일 때. 벽을 다 세웠으므로, 바이러스가 퍼져나가는것을 dfs를 통해 시뮬레이션한다. int result = init_safe; int[][] sub_map = new int[map.length][map[0].length]; for (int i = 0; i < sub_map.length; i++) sub_map[i] = map[i].clone(); // 기존 맵을 복사해 시뮬레이션용 맵을 새로 만든다. Queue<Cord> queue = new LinkedList<>(virus); while (!queue.isEmpty()) { Cord elem = queue.poll(); for (int i = 0; i < 4; i++) { int nx = dx[i] + elem.x; int ny = dy[i] + elem.y; if (nx >= 0 && nx < map.length && ny >= 0 && ny < map[0].length && sub_map[nx][ny] == 0) { queue.add(new Cord(nx, ny)); sub_map[nx][ny] = 2; result--; } } } if (result > answer) answer = result; } else { for (int i = x; i < map.length; i++) { for (int j = 0; j < map[0].length; j++) { if (map[i][j] == 0) { map[i][j] = 1; bfs(i, depth + 1); map[i][j] = 0; } } } } } public static void main(String[] args) { Scanner scan = new Scanner(System.in); int N = scan.nextInt(); int M = scan.nextInt(); scan.nextLine(); map = new int[N][M]; virus = new ArrayList<>(); init_safe = 0; // 초기 안전영역의 크기 for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { map[i][j] = scan.nextInt(); if (map[i][j] == 2) virus.add(new Cord(i ,j)); else if (map[i][j] == 0) init_safe++; } scan.nextLine(); } init_safe -= 3; // 벽을 세울것이기 때문에, 최대 벽 개수인 3개를 미리 빼줌(안전영역이 아님) answer = 0; bfs(0, 0); System.out.println(answer); } }
'Baekjoon' 카테고리의 다른 글
백준(BOJ) 25401 - 카드바꾸기 (1) 2023.12.07 1092 - 배 (0) 2023.09.07 1074 - Z (0) 2022.12.07 2580 - 스도쿠 (0) 2022.05.30 16197 - 두 동전 (0) 2022.05.28