알고리즘/백준
16236번 - 아기 상어
fleur75
2023. 8. 20. 18:09
1️⃣ BFS, PriorityQueue
✏️ 풀이 과정
문제에서 해결해야 할 부분은 다음에 먹을 물고기를 찾는 것과 물고기를 크기만큼 먹었을 때 상어의 크기를 올려주는 것입니다.
먹을 물고기를 찾기 위해서는 두 가지 처리가 필요한데 한 가지는 이동 거리 계산을 위해서 큐 사이즈를 이용하는 BFS를 사용하는 것입니다. 그리고 나머지 한 가지는 거리가 같을 때의 우선 순위를 고려하기 위해서 PriorityQueue를 사용하는 것입니다.(ArrayList에 넣고 정렬하는 것도 상관없습니다.)
물고기 한 마리를 먹을 때마다 BFS를 통해 거리마다 탐색하고 가능한 목표가 있을 때 이동 거리를 반환하면서 while문을 돌려야 합니다. 더 이상 먹을 물고기가 없는 경우에 -1 등의 표시를 반환하여 로직을 종료하면 문제가 해결됩니다.
크기의 경우 BFS를 완료하고 먹은 물고기를 확정할 때 카운팅하면서 현재 개수가 크기와 같으면 크기를 올려주며 개수를 초기화하면 됩니다. 이 크기와 물고기 크기의 비교를 BFS의 continue 로직에서 수행합니다.
⏱ 시간 복잡도
각 BFS는 O(N^2)인데 N^2번 반복될 수 있기 때문에 시간 복잡도는 O(N^4)가 됩니다. N이 20까지 가능하기 때문에 대략 160000번 가량의 계산으로 문제가 해결됩니다.
💻 코드
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static class Point implements Comparable<Point> {
int r;
int c;
public Point(int r, int c) {
this.r = r;
this.c = c;
}
@Override
public int compareTo(Point o) {
if(this.r == o.r) {
return this.c-o.c;
} else {
return this.r-o.r;
}
}
}
static int[] dr = {-1, 1, 0, 0};
static int[] dc = {0, 0, -1, 1};
static int[][] map;
static int N, curR, curC, curS, curCnt;
static int bfs() {
LinkedList<Point> q = new LinkedList<>();
PriorityQueue<Point> pq = new PriorityQueue<>();
boolean[][] visited = new boolean[N][N];
q.offer(new Point(curR, curC));
Point cur;
int res = 0;
int time = 0;
while(!q.isEmpty()) {
int size = q.size();
time++;
for(int i=0;i<size;i++) {
cur = q.poll();
for(int j=0;j<4;j++) {
int nr = cur.r + dr[j];
int nc = cur.c + dc[j];
if(nr < 0 || nc < 0 || nr >= N || nc >= N || visited[nr][nc] || map[nr][nc] > curS) {
continue;
}
visited[nr][nc] = true;
q.offer(new Point(nr, nc));
if(map[nr][nc] > 0 && map[nr][nc] < curS) {
pq.offer(new Point(nr, nc));
}
}
}
if(!pq.isEmpty()) {
cur = pq.poll();
curCnt++;
if(curCnt == curS) {
curS++;
curCnt = 0;
}
curR = cur.r;
curC = cur.c;
res = time;
map[cur.r][cur.c] = 0;
break;
}
}
if(res == 0) {
return -1;
}
return res;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
map = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 9) {
curR = i;
curC = j;
map[i][j] = 0;
}
}
}
int ans = 0;
int tmp;
curS = 2;
curCnt = 0;
while(true) {
tmp = bfs();
if(tmp == -1) {
break;
}
ans += tmp;
}
System.out.println(ans);
br.close();
}
}