[백준][Java] 14502번 : 연구소

2025. 6. 1. 18:36·PS/이코테

[문제 링크]

https://www.acmicpc.net/problem/14502


문제 설명

0 - 빈 칸, 1 - 벽, 2 - 바이러스

빈 칸에 벽을 3개 세워서 바이러스가 퍼지는 것을 최소로 한다.

이 때, 바이러스가 퍼질 수 없는 곳인 안전 영역 크기의 최대값을 구한다.

 

 

 

 

 

 

문제 풀이

  • 이 문제를 풀기 위해서는 크게 세 가지로 나눌 수 있다.
    1. 3개의 벽을 세우는 경우의 수 구하기 →  DFS
    2. 벽 3개를 세운 후 바이러스가 퍼지는 과정 구하기 →  BFS
    3. 안전영역의 크기를 구하고 안전영역의 최대값 구하기

그 전에, 입력받을 때 바이러스의 위치 정보를 따로 리스트에 저장했다.(바이러스가 퍼지는 것을 계산할 때 사용하기 위해서)

//바이러스가 있는 위치를 리스트에 따로 저장
if (map[i][j] == 2) {
virusPositions.add(new Virus(i, j));
}

 

1. 3개의 벽을 세우는 경우의 수 구하기  → DFS

DFS를 통해서 3개의 벽을 세우는 모든 경우의 수를 구한다.

public static void dfs(int cnt) {
    if (cnt == 3) {
        virus();
        return;
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (map[i][j] == 0) {
                map[i][j] = 1;
                dfs(cnt + 1);
                map[i][j] = 0;
            }
        }
    }
}

 

 

2. 바이러스가 퍼지는 과정 구하기 → BFS

DFS로 각 바이러스마다 퍼지는 것을 계산한다.

public static void bfs(int x, int y) {
    queue.offer(new Virus(x, y));

    while (!queue.isEmpty()) {
        Virus poll = queue.poll();
        x = poll.x;
        y = poll.y;

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (nx < 0 || ny < 0 || nx >= n || ny >= m) {
                continue;
            }
            if (copyMap[nx][ny] == 0) {
                copyMap[nx][ny] = 2;
                queue.offer(new Virus(nx, ny));
            }
        }
    }
}

 

2. 안전영역의 크기를 구하고 안전영역의 최대값 구하기

public static void countSafeArea() {
    int safeArea = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (copyMap[i][j] == 0) {
                safeArea++;
            }
        }
    }

    maxSafeArea = Math.max(maxSafeArea, safeArea);  //안전영역 최댁랎 구하기
}

 

 

 

전체 코드

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

class Virus {
    int x;
    int y;

    public Virus(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Main {

    static int n, m;
    static int maxSafeArea = Integer.MIN_VALUE;
    static int[][] map, copyMap;
    static ArrayList<Virus> virusPositions = new ArrayList<>(); //바이러스의 위치를 담는 리스트
    static Queue<Virus> queue = new LinkedList<>();
    //바이러스의 이동방향
    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());

        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());
                //바이러스가 있는 위치를 리스트에 따로 저장
                if (map[i][j] == 2) {
                    virusPositions.add(new Virus(i, j));
                }
            }
        }

        dfs(0);
        System.out.println(maxSafeArea);
    }

    public static void dfs(int cnt) {
        //새로 새운 벽이 3개일 경우
        if (cnt == 3) {
            virus();    //바이러스가 퍼지고 안전영역 구하기
            return;
        }

        //처음부터 순서대로 돌면서 '0' 부분에 벽 세우고 재귀호출
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 0) {
                    map[i][j] = 1;
                    dfs(cnt + 1);
                    map[i][j] = 0;
                }
            }
        }
    }

    public static void virus() {
        copyMap = new int[n][m];

        //원본 배열은 그대로 두고 복사
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                copyMap[i][j] = map[i][j];
            }
        }

        //각 바이러스 위치에서 전파 시작
        for (Virus v : virusPositions) {
            bfs(v.x, v.y);
        }
        //안전영역의 크기 구하기
        countSafeArea();
    }

    //바이러스가 퍼지는 것을 계산하는 함수
    public static void bfs(int x, int y) {
        queue.offer(new Virus(x, y));

        while (!queue.isEmpty()) {
            Virus poll = queue.poll();
            x = poll.x;
            y = poll.y;

            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];

                //공간을 벗어날 경우 무시
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) {
                    continue;
                }
                if (copyMap[nx][ny] == 0) {
                    copyMap[nx][ny] = 2;
                    queue.offer(new Virus(nx, ny));
                }
            }
        }
    }


    //안전 영역의 크기를 세는 함수
    public static void countSafeArea() {
        int safeArea = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (copyMap[i][j] == 0) {
                    safeArea++;
                }
            }
        }

        maxSafeArea = Math.max(maxSafeArea, safeArea);  //안전영역 최댁랎 구하기
    }
}



저작자표시 비영리 변경금지 (새창열림)

'PS > 이코테' 카테고리의 다른 글

[이코테][Java] 문자열 압축  (0) 2025.06.01
[이코테][Java] 퇴사  (0) 2025.05.12
[이코테][Java] 연산자 끼워넣기  (0) 2025.05.12
[이코테][Java] 병사 배치하기  (0) 2025.04.29
[이코테][Java] 편집거리  (0) 2025.04.27
'PS/이코테' 카테고리의 다른 글
  • [이코테][Java] 문자열 압축
  • [이코테][Java] 퇴사
  • [이코테][Java] 연산자 끼워넣기
  • [이코테][Java] 병사 배치하기
nyrimmm
nyrimmm
  • nyrimmm
    개발기록
    nyrimmm
  • 전체
    오늘
    어제
  • 글쓰기 관리
    • 분류 전체보기 (76)
      • Java (6)
      • Spring & SpringBoot (3)
      • Network (1)
      • DataBase (0)
      • SQL (1)
      • IntelliJ (3)
      • Git (0)
      • 자료구조 & 알고리즘 (2)
      • 트러블 슈팅 (1)
        • Spring (1)
      • PS (58)
        • 백준 (16)
        • 프로그래머스 (0)
        • SQL (9)
        • 이코테 (33)
      • 후기 & 회고 (1)
  • 태그

  • 인기 글

  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
nyrimmm
[백준][Java] 14502번 : 연구소
상단으로

티스토리툴바