[Gold III] 16236번:아기상어 - 문제 풀러가기
거리가 가까운 물고기 여러 마리 -> 상단
상단에 여러 마리 -> 왼쪽
=> 테스트 케이스 3번에서 주의할 점
이 기준이 BFS검사할떄 위 왼쪽 오른쪽 아래 기준이 아니라 배열 전체 기준으로 위, 왼쪽을 기준으로 해야됩니다
1. 최단경로 => BFS - 시작 정점에서 가까운 정점부터 차례대로 탐색
2. BFS + queue 함께 사용
dx, dy는 x, y 좌표의 변화량이므로 상하좌우 네 방향에 대해서는 다음 값을 가집니다.
static int[] dx = {0, 0 , -1 ,1}; // 상 하 좌 우
static int[] dy = {-1, 1, 0, 0};
a. 처음 상어의 위치에서 먹을 수 있는 물고기는 [1], [2]로 거리는 동일하지만,
위치 우선순위상 [1]쪽으로 먼저간다. → Total Distance: 3
b. 아직 상어의 크기는 2이므로 [2]로 이동한다. 크기 Up(=3) → Total Distance: 3 + 6 = 9
c. 바로 오른쪽 [3]의 위치로 간다. → Total Distance: 9 + 1 = 10
d. 그 다음 유일한 먹이인 [4]의 위치로 간다. → Total Distance: 10 + 4 = 14
e. 상어의 크기보다 작은 물고기가 없으므로 종료
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N, sharkRow, sharkCol, sharkSize = 2, eatCnt = 0;
static int answer = 0; // 결과값
static int map[][];
static int[] dx = {0, 0, -1, 1}; // 상 하 좌 우
static int[] dy = {-1, 1, 0, 0};
static boolean[][] visited;
static Queue<Node> queue;
public static void main(String arg[]) 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) { // 상어인 경우
sharkRow = i;
sharkCol = j;
map[i][j] = 0;
}
}
}
while (true) {
if (!BFS()) break;
}
System.out.println(answer);
}
private static boolean BFS() {
visited = new boolean[N][N];
queue = new LinkedList<>();
queue.add(new Node(sharkRow, sharkCol, 0));
visited[sharkRow][sharkCol] = true;
int minDistance = Integer.MAX_VALUE;
int minX = N, minY = N;
while (!queue.isEmpty()) {
Node node = queue.poll();
if (node.distance > minDistance) break; // 더 이상 탐색할 필요 없음
for (int i = 0; i < 4; i++) { // 상하좌우 방향
int nx = node.x + dx[i];
int ny = node.y + dy[i];
int dis = node.distance + 1;
if (nx >= 0 && ny >= 0 && nx < N && ny < N && !visited[nx][ny] && map[nx][ny] <= sharkSize) {
visited[nx][ny] = true;
queue.add(new Node(nx, ny, dis));
// 물고기를 찾은 경우
if (map[nx][ny] > 0 && map[nx][ny] < sharkSize) {
if (dis < minDistance) {
minDistance = dis;
minX = nx;
minY = ny;
} else if (dis == minDistance) {
if (nx < minX || (nx == minX && ny < minY)) {
minX = nx;
minY = ny;
}
}
}
}
}
}
if (minX != N && minY != N) { // 먹을 수 있는 물고기가 있는 경우
map[minX][minY] = 0; // 물고기 먹기
sharkRow = minX;
sharkCol = minY;
eatCnt++;
if (eatCnt == sharkSize) { // 상어 크기 증가
sharkSize++;
eatCnt = 0;
}
answer += minDistance;
return true;
}
return false; // 더 이상 먹을 물고기가 없는 경우
}
public static class Node {
int x, y, distance;
public Node(int x, int y, int distance) {
this.x = x;
this.y = y;
this.distance = distance;
}
}
}