[프로그래머스/LV2] 석유시추 - bfs (Java)
[프로그래머스/LV2] 석유시추 문제를 Java로 해결한 풀이입니다. bfs로 설명합니다.
[PCCP 기출문제] 2번 / 석유 시추
🙋♂️ 들어가며
- row <= 500
- col <= 500
상황에서 각좌표마다 그냥 bfs를 하면 25000 * 500 * 500으로 시간초과였다.
그래서 각 좌표마다 1번씩만 돌아서 최악의 연산횟수가 총 250000으로 만들어질 필요가 있었다.
그러려면 방문한 좌표는 더이상 방문하면 안됬었고 이를 위해 Set을 추가하였으며
석유에 인접한 열번호를 추가하고자 하였다.
입출력예 2번 기준으로 land[0][0] 일때 석유인 곳을 계속 방문하여 연결하면
set = {0, 1, 2, 3, 4, 5, 6}
즉 모든 열번호가 들어오게 된다
그 과정에서 석유를 찾을 때마다 석유 시작점 1에서 ++를 해주었고
bfs 종료 후에, column_arr에 set의 번호를 적용해 총 석유의 갯수를 더해주었다
이 과정은 O(row*col) 이며 코드는 다음과 같다
✅ 정답
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import java.util.Set;
import java.util.HashSet;
import java.util.ArrayDeque;
import java.util.Queue;
class Solution {
static int answer;
static int row, col;
static int[] dr = {-1,1,0,0};
static int[] dc = {0,0,-1,1};
public int solution(int[][] land) {
answer = 0;
// O(row * col)
// visited 배열로 이미 방문한 곳은 재방문 없이 25만 이내에 해결
// column을 중복없이 저장하기 위해 Set
// 1-1. 완전탐색
row = land.length;
col = land[0].length;
boolean[][] visited = new boolean[row][col];
int[] column_arr = new int[col];
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
// 1-2. 1이고 방문 안했으면 bfs
if (land[r][c] == 1 && !visited[r][c]) {
int sr = r;
int sc = c;
bfs(sr, sc, land, visited, column_arr);
}
}
}
// 3. 각 열마다 검사하여 최댓값 추출
for (int i = 0; i < column_arr.length; i++) {
answer = Math.max(column_arr[i], answer);
}
return answer;
}
// 2. 함수 (bfs)
static void bfs(int cr, int cc, int[][] land, boolean[][] visited, int[] column_arr) {
// 2-0. 석유영역 갯수 (현재영역도 석유라서 1부터 시작)
int cnt = 1;
// 2-1. Set 생성, q생성
Set<Integer> col_no = new HashSet<>();
Queue<int[]> q = new ArrayDeque<>();
// 2-2. 초기값 true 처리후, q에 삽입, 컬럼번호 추가
visited[cr][cc] = true;
q.add(new int[] {cr, cc});
col_no.add(cc);
// 2-3. q가 비지않았을 때까지 검사
while (!q.isEmpty()) {
int[] cur = q.poll();
int cur_r = cur[0];
int cur_c = cur[1];
for (int d = 0; d < 4; d++) {
int nr = cur_r + dr[d];
int nc = cur_c + dc[d];
// 2-3-a. 만약 범위 밖이면 -> continue;
if (nr < 0 || nr >= row || nc < 0 || nc >= col) continue;
// 2-3-b. 만약 이미 방문했거나, 흙이면 skip
if (visited[nr][nc] || land[nr][nc] == 0) continue;
// 2-3-c. 범위안, 미방문, 석유면?
visited[nr][nc] = true;
cnt++;
q.add(new int[] {nr, nc});
col_no.add(nc);
}
}
// 2-4. 석유 걸치고 있는 영역 갯수에 반영
for (int no : col_no) {
column_arr[no] += cnt;
}
// 2-5. 종료
return;
}
}
This post is licensed under CC BY 4.0 by the author.

