anott
기록
anott
  • 분류 전체보기
    • 오라클
    • SQL
    • 알고리즘
      • 백준저지
      • 프로그래머스
      • SWEA
    • 개발 관련
    • 프론트엔드
      • TypeScript, Next.js
      • React 공식문서 읽기
hELLO · Designed By 정상우.
anott

기록

백준저지 14502번 연구소
알고리즘/백준저지

백준저지 14502번 연구소

2021. 9. 26. 23:58

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

 

14502번: 연구소

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

www.acmicpc.net

 

 

 

접근 방법

입력을 받을 때 빈칸의 위치를 리스트에, 바이러스의 위치를 큐에 담는다.

빈칸 위치들 중 3개를 조합으로 뽑아내서 벽을 세운다. 그리고 그때마다 bfs로 바이러스를 퍼뜨리고 안전영역의 수를 구한다. 이렇게 하기 위해서 맵과 큐는 매번 복사해서 사용한다.

그렇게 구한 안전영역들의 최소값이 답이 된다.

 

 

 

생각

조합 + BFS (토마토(https://www.acmicpc.net/problem/7576)) 문제였다.

 

 

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ14502 {
    static int N, M, map[][], answer;
    static Queue<Position> q; // 바이러스 위치를 저장할 큐
    static ArrayList<Position> arrToPutWall; // 빈칸 위치를 저장할 리스트
    static Position[] selected; // 벽을 세우기 위해 빈칸 3개를 고르고 해당 위치를 저장할 리스트
    static int[][] d = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };

    static class Position { // 위치
        int x, y;

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

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        map = new int[N][M];
        q = new LinkedList<>();
        arrToPutWall = new ArrayList<>();
        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) { // 바이러스 위치 큐에 넣기
                    q.offer(new Position(i, j));
                } else if (map[i][j] == 0) { // 빈 칸 위치 리스트에 넣기
                    arrToPutWall.add(new Position(i, j));
                }
            }
        }

        answer = Integer.MIN_VALUE; // 답은 최소값으로 초기화
        selected = new Position[3]; // 3개의 빈칸을 고를 것
        pickThree(0, 0); // 조합으로 3개의 벽을 놓을 곳 찾기

        System.out.println(answer); // 답 출력
    }

    private static void pickThree(int cnt, int start) {
        if (cnt == 3) {
            int[][] copyMap = Arrays.stream(map).map(int[]::clone).toArray(int[][]::new); // 맵 복사
            for (int i = 0; i < 3; i++) {
                int x = selected[i].x;
                int y = selected[i].y;
                copyMap[x][y] = 1; // 복사된 맵의 빈칸 3군데에 벽을 세우기
            }
            Queue<Position> copyQ = new LinkedList<>(q); // 큐 복사

            spreadVirus(copyQ, copyMap); // 복사된 큐와 맵을 가지고 bfs

            return;
        }

        for (int i = start; i < arrToPutWall.size(); i++) {
            selected[cnt] = arrToPutWall.get(i);
            pickThree(cnt + 1, i + 1);
        }
    }

    private static void spreadVirus(Queue<Position> copyQ, int[][] copyMap) {
        while (!copyQ.isEmpty()) {
            Position pos = copyQ.poll();

            for (int i = 0; i < 4; i++) {
                int dx = pos.x + d[i][0];
                int dy = pos.y + d[i][1];
                if (dx >= 0 && dx < N && dy >= 0 && dy < M && copyMap[dx][dy] == 0) { // 빈칸이 있다면 이동
                    copyMap[dx][dy] = 2;
                    copyQ.offer(new Position(dx, dy));
                }
            }
        }

        int cnt = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cnt += (copyMap[i][j] == 0) ? 1 : 0; // 안전 영역 크기 개수 세기
            }
        }
        answer = Math.max(answer, cnt); // 안전 영역 크기의 최댓값 구하기
    }
}

 

저작자표시 비영리 (새창열림)

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

백준저지 2206번 벽 부수고 이동하기 (Java)  (0) 2021.10.04
백준저지 1755번 숫자놀이  (0) 2021.09.27
백준저지 2667번 단지번호붙이기  (0) 2021.09.20
백준저지 1463번 1로 만들기  (0) 2021.09.15
백준저지 9095번 1, 2, 3 더하기  (0) 2021.09.14
    '알고리즘/백준저지' 카테고리의 다른 글
    • 백준저지 2206번 벽 부수고 이동하기 (Java)
    • 백준저지 1755번 숫자놀이
    • 백준저지 2667번 단지번호붙이기
    • 백준저지 1463번 1로 만들기
    anott
    anott

    티스토리툴바