| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- 15686
- 구현
- 1932
- 자바
- 조합
- BFS
- 깃허브
- 분할정복
- 완전탐색
- 알고리즘고득점Kit
- 다익스트라
- Lv2
- 그래프탐색
- DP
- dfs
- 정렬
- Summer/Winter Coding(~2018)
- 프로그래멋
- 깃허브 프로필
- Java
- 토마토
- GIT
- 월간 코드 챌린지 시즌1
- 그래프
- 정수 삼각형
- 알고리즘
- 프로그래머스
- 이코테
- Python
- 백준
Archives
- Today
- Total
갱스터하우스
[Java] 백준 14502.연구소 본문
➡️문제 링크
https://www.acmicpc.net/problem/14502
💡아이디어
조합과 bfs
✏️문제 풀이
1. 조합, bfs - 성공
(1) 빈 칸에서 바이러스를 막아줄 벽 3개를 뽑는다.(조합)
(2) (1) 에서 추출한 벽을 바탕으로 바이러스 확산한다.(bfs)
(3) 확산 후, 남아있는 빈칸을 비교하면 최대 영역의 수 갱신하기
처음에는 확산 후, 남아있는 빈칸을 비교할 때 매번 이중 for문을 돌면서 빈칸을 세야하나 고민했다.
그러다 빈칸의 총 수를 먼저 구해놓고, 확산할때마다 한 칸씩 감소하는 게 더 효율적이라고 생각했다.
import java.io.*;
import java.util.*;
/*
* 1. 3개의 벽 조합으로 구하기
* 2. 1의 결과로 바이러스 확산
* 3. 이 후 안전영역 갱신
* */
public class Main {
static int N, M;
static int [][] map;
static boolean [][] visited;
static int [] dx = {-1, 0, 1, 0};
static int [] dy = {0, 1, 0, -1};
static List<int []> virous = new ArrayList<>();
static int maxArea = 0;
static int count = 0;
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
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];
visited = new boolean[N][M];
List<int []> empty = 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] == 0) empty.add(new int[] {i, j}); // 빈 칸
if(map[i][j] == 2) virous.add(new int[] {i, j}); // 바이러스
}
}
// 3개 조합 구하기
count = empty.size();
recursion(empty, new int [3][2], 0, 0);
// 정답 출력
System.out.println(maxArea);
}
static void recursion(List<int []> list, int [][] arr, int depth, int idx) {
if(depth == 3) {
for(int [] ar : arr) {
map[ar[0]][ar[1]] = 1; // 벽 설치
}
bfs();
// 벽 설치 취소
for(int [] ar : arr) {
map[ar[0]][ar[1]] = 0; // 원래 값으로 복구
}
return;
}
for(int i = idx; i < list.size(); i++) {
arr[depth][0] = list.get(i)[0];
arr[depth][1] = list.get(i)[1];
recursion(list, arr, depth+1, i+1);
}
}
static void bfs() {
Queue<int []> que = new LinkedList<>(virous);
for(int [] arr : virous) {
visited[arr[0]][arr[1]] = true;
}
int cnt = count-3; // 빈자리에 3개의 벽 설치했으니까
while(!que.isEmpty()) {
int [] point = que.poll();
if(cnt <= maxArea) break;
for(int i = 0; i < 4; i++) {
int tx = point[0] + dx[i];
int ty = point[1] + dy[i];
if(!checkRange(tx, ty)) continue; // 범위 밖
if(visited[tx][ty] || map[tx][ty] != 0) continue; // 이미 방문 or 빈 칸 아닌 경우
visited[tx][ty] = true;
que.add(new int [] {tx, ty});
cnt--;
}
}
// visited 초기화
for(boolean [] v : visited) {
Arrays.fill(v, false);
}
// 최댓값 갱신
maxArea = Math.max(maxArea, cnt);
}
static boolean checkRange(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < M;
}
}
'코테 문제 > 백준' 카테고리의 다른 글
| [Java] 백준 14938.서강그라운드 (0) | 2026.04.01 |
|---|---|
| [Java] 백준 14503.로봇 청소기 (0) | 2026.03.27 |
| [Java] 백준 1753.최단 경로 (0) | 2026.03.17 |
| [Java] 백준 15686.치킨 배달 (0) | 2026.03.13 |
| [Java] 백준 13549.숨바꼭질 3 (0) | 2026.03.12 |