갓생사는 김초원의 개발 블로그
chocho_log
갓생사는 김초원의 개발 블로그
전체 방문자
오늘
어제
  • 분류 전체보기 (76)
    • 개발 (22)
      • Spring (4)
      • Java (3)
      • Database (2)
      • Elasticsearch (3)
      • ETC (3)
      • JPA (3)
      • 이슈 (1)
    • 코딩 테스트 (43)
      • 프로그래머스 (23)
      • 백준 (12)
      • TIP (8)
    • 자료구조 (2)
    • 알고리즘 (4)
    • 잡생각 (0)
    • 경험 (3)
      • AWS re:Invent 2024 (3)

블로그 메뉴

    공지사항

    인기 글

    태그

    • jar
    • Spring Boot Embedded Tomcat
    • Lazy Loading
    • war
    • 지연로딩
    • querydsl
    • jpa
    • 디자인패턴 #SOLID 원칙

    최근 댓글

    최근 글

    갓생사는 김초원의 개발 블로그

    chocho_log

    코딩 테스트/백준

    [백준][gold5] 14502번: 연구소 - JAVA

    2021. 5. 8. 21:37

    [문제]

    www.acmicpc.net/problem/14502

     

    14502번: 연구소

    인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

    www.acmicpc.net

    [풀이 내용]

    * 알고리즘 분류

    - 부르트포스 알고리즘

    - 너비 우선 탐색 

     

    0으로 표시된 빈칸들 중에 3곳을 골라 벽을 세워야 한다.

    어떻게 3곳을 골라야 가장 안전 영역을 많이 확보할 수 있는지 모르므로 경우의 수를 모두 해봐야 한다. 

    그 다음 각 경우마다 바이러스가 퍼질 수 없는 안전 영역의 크기를 구하고 그 중 최댓값을 출력한다. 

     

    1. 연구소 2차원 배열에서 0으로 표시된 칸들 중에 3가지를 선택하는 경우의 수를 모두 구했다. 

    예를 들어 0인 칸이 20개라면 20개중에 3개를 선택하는 것이므로 20C3 인 조합의 개수와 같다.

     

    2. 경우의 수마다 모두 다음 과정을 실행한다. 

     2-1. 연구소 2차원 배열에서 선택된 3개의 칸을 1로 변경한다. (원래는 모두 0이었을 테니)

     2-2. 연구소에서 처음부터 2(바이러스에 감염된)였던 곳들을 너비우선탐색을 통해 위, 아래, 왼쪽, 오른쪽을 탐색하며 전파 할 수 있는지 여부를 확인한다. 전파할 수 있다면 카운트를 1증가한다. 

     2-3. 전파할 수 있는 카운트를 구했으면 남은 0의 개수(안전 영역)을 구한다. 

              = 원래 0의 개수 - 전파될 수 있는 곳의 개수(0->2) - 3(3군데는 0-> 1로 변경했으므로) 

     

    [코드]

    package com.algorithm.baekjoon.gold5;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.StringTokenizer;
    
    public class Test02 {
        public static int N; // 행
        public static int M; // 열
        public static int[][] lab; // 연구소
        public static List<int[]> infectPlaceList = new ArrayList<>(); // 처음부터 감염된 칸들
        public static boolean[][] infected; // 감염이 전파된 여부
        public static int zeroCount = 0; // 빈칸의 개수
        public static int count = 0; // 감염이 전파된 칸의 개수
        public static int max = Integer.MIN_VALUE; // 정답
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    
            StringTokenizer st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            lab = new int[N][M];
            infected = new boolean[N][M];
    
            int num = N * M;
            int[] buckets = new int[3];
    
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < M; j++) {
                    int n = Integer.parseInt(st.nextToken());
                    lab[i][j] = n;
    
                    if (n == 0) {
                        zeroCount++;
                    }
    
                    if (n == 2) {
                        int[] infectedPlace = {i, j};
                        infectPlaceList.add(infectedPlace);
                    }
                }
            }
    
            getMaxOfSafeZone(num, buckets, buckets.length);
            bw.write(max + "\n");
    
            br.close();
            bw.flush();
            bw.close();
        }
    
        private static void getMaxOfSafeZone(int nums, int[] buckets, int k) {
            if (k == 0) {
                count = 0;
                for (int i = 0; i < buckets.length; i++) {
                    int quo = buckets[i] / M; // 행
                    int remain = buckets[i] % M; // 렬
                    lab[quo][remain] = 1;
                }
    
                for (int[] infectedPlace : infectPlaceList) {
                    getInfectedPlace(infectedPlace[0], infectedPlace[1]);
                }
    
                max = Math.max(max, zeroCount - count - 3);
                infected = new boolean[N][M];
    
                for (int i = 0; i < buckets.length; i++) {
                    int quo = buckets[i] / M; // 행
                    int remain = buckets[i] % M; // 렬
                    lab[quo][remain] = 0;
                }
                return;
            }
    
            int lastIndex = buckets.length - k - 1;
    
            for (int i = 0; i < nums; i++) {
                int quo = i / M; // 행
                int remain = i % M; // 렬
                if (lab[quo][remain] == 0) {
                    if (buckets.length == k) {
                        buckets[0] = i;
                        getMaxOfSafeZone(nums, buckets, k - 1);
                    } else {
                        if (buckets[lastIndex] < i) {
                            buckets[lastIndex + 1] = i;
                            getMaxOfSafeZone(nums, buckets, k - 1);
                        }
                    }
                }
            }
        }
    
        public static void getInfectedPlace(int x, int y) {
            infected[x][y] = true;
    
            // 위
            if (checkValidation(x - 1, y) && lab[x - 1][y] == 0 && !infected[x - 1][y]) {
                count++;
                getInfectedPlace(x - 1, y);
            }
    
            // 아래
            if (checkValidation(x + 1, y) && lab[x + 1][y] == 0 && !infected[x + 1][y]) {
                count++;
                getInfectedPlace(x + 1, y);
            }
    
            // 왼
            if (checkValidation(x, y - 1) && lab[x][y - 1] == 0 && !infected[x][y - 1]) {
                count++;
                getInfectedPlace(x, y - 1);
            }
    
            // 오
            if (checkValidation(x, y + 1) && lab[x][y + 1] == 0 && !infected[x][y + 1]) {
                count++;
                getInfectedPlace(x, y + 1);
            }
        }
    
        public static boolean checkValidation(int x, int y) {
            if (x < 0 || x >= lab.length || y < 0 || y >= lab[x].length) {
                return false;
            }
            return true;
        }
    }
    

    '코딩 테스트 > 백준' 카테고리의 다른 글

    [백준][Gold5] 12865 - 평범한 배낭 - JAVA  (0) 2021.05.16
    [백준][gold5] 9251번: LCS - JAVA  (0) 2021.05.09
    [백준][Gold1]11401-이항계수3-JAVA  (0) 2021.04.27
    [백준][Gold1] 구간 합 구하기 - JAVA  (0) 2021.04.13
    [백준][Gold1] 책 페이지 - JAVA  (0) 2021.04.10
      '코딩 테스트/백준' 카테고리의 다른 글
      • [백준][Gold5] 12865 - 평범한 배낭 - JAVA
      • [백준][gold5] 9251번: LCS - JAVA
      • [백준][Gold1]11401-이항계수3-JAVA
      • [백준][Gold1] 구간 합 구하기 - JAVA
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그 github: https://github.com/kimchowon

      티스토리툴바