티스토리 뷰
문제 - (https://www.acmicpc.net/problem/16236)
아기상어가 상좌우하로 이동하면서 자신이 먹을 수 있는 물고기를 먹다가 더이상 먹을 수 있는 물고기가 없을 때 걸린 시간을 리턴하는 문제다.
아기상어가 물고기를 먹기 위한 조건이 있는데,
1. 더 이상 먹을 수 있는 물고기가 공간에 없다면 아기 상어는 엄마 상어에게 도움을 요청한다. == 종료조건
2. 먹을 수 있는 물고기가 1마리라면, 그 물고기를 먹으러 간다.
3. 먹을 수 있는 물고기가 1마리보다 많다면, 거리가 가장 가까운 물고기를 먹으러 간다.
- 거리는 아기 상어가 있는 칸에서 물고기가 있는 칸으로 이동할 때, 지나야하는 칸의 개수의 최솟값이다.
- 거리가 가까운 물고기가 많다면, 가장 위에 있는 물고기, 그러한 물고기가 여러마리라면, 가장 왼쪽에 있는 물고기를 먹는다.
3-1을 통해 현재 상어의 위치에서 먹을 수 있는 물고기까지의 "최단거리"를 구해야 하는 것을 알 수 있고, 최단거리는 BFS를 사용하는 것이 좋으므로 (굳이 DFS를 사용해서 모든 경우를 살펴볼 필요 없이, BFS로 최단거리 내에 먹을 수 있는 물고기를 발견하면 더이상 진행하지 않고 그 물고기를 먹으면 되므로) 어떤 알고리즘을 사용할 지 방향을 정할 수 있다.
3-2를 만족하기 위해 나는 우선순위 큐를 사용했다.
static class Pos {
int y;
int x;
int distance;
Pos(int y, int x, int distance) {
this.y = y;
this.x = x;
this.distance = distance;
}
}
Queue<Pos> q = new PriorityQueue<>((o1, o2) -> {
if (o1.distance == o2.distance) {
if (o1.y == o2.y) return Integer.compare(o1.x, o2.x);
return Integer.compare(o1.y, o2.y);
}
return Integer.compare(o1.distance, o2.distance);
});
현재 상어의 위치로부터 거리가 같은 물고기인 경우 x, y 좌표를 확인하여 큐에 삽입한다.
- 가장 위에 있는 물고기 => y좌표가 더 작음
- 가장 왼쪽에 있는 물고기 => x좌표가 더 작음
📌배운 것
- 상어가 이동할 위치를 큐에 담을 때, 현재 상어와의 거리, 좌표를 기록할 수 있는 클래스를 생성하기
- 최단거리 알고리즘이 필요할 땐 BFS 사용하기
😅실수
- 상어를 '상 좌 우 하'로 이동시킬 때마다 이전에 왔던 곳은 visited에 표시해두어 다시 접근하지 않도록 한다.
ex) 1,1에서 0,1로 이동했을 때, 다시 1,1로 가서 무한반복되는 경우 - 한 번의 BFS로 답을 찾으려고 하니 어려웠던 문제다. 상어의 위치에서 가장 가까운 먹을 수 있는 물고기를 찾는 BFS를 진행하고, 발견한다면 상어를 그 위치로 이동시키고 그 위치에서 다시 BFS를 시작한다는 로직을 생각할 수 있어야 한다.
이때, "다시 시작"하는 것이므로 초기화해야 할 것들은 다시 초기화한다. visited라던지, 큐에 담겨져있는 것들을 비운다던지..
참고: https://mygumi.tistory.com/339 [마이구미의 HelloWorld]
코드
public class BabyShark_RIGHT {
static int n;
static int sharkY;
static int sharkX;
static int sharkSize = 2;
static int eatCnt;
// 상좌우하 dy dx
static int[] dy = {-1, 0, 0, 1};
static int[] dx = {0, -1, 1, 0};
static int answer;
static boolean[][] visited;
static class Pos {
int y;
int x;
int distance;
Pos(int y, int x, int distance) {
this.y = y;
this.x = x;
this.distance = distance;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
int[][] 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] != 0) {
if (map[i][j] == 9) {
sharkY = i;
sharkX = j;
map[i][j] = 0; // 처음 상어의 위치는 0으로 초기화
}
}
}
}
Queue<Pos> q = new PriorityQueue<>((o1, o2) -> {
if (o1.distance == o2.distance) {
if (o1.y == o2.y) return Integer.compare(o1.x, o2.x);
return Integer.compare(o1.y, o2.y);
}
return Integer.compare(o1.distance, o2.distance);
});
// 상어의 처음 위치 큐에 삽입
q.add(new Pos(sharkY, sharkX, 0));
visited = new boolean[n][n];
visited[sharkY][sharkX] = true;
while (!q.isEmpty()) {
Pos curPos = q.poll(); // 상어의 현재 위치
for (int i = 0; i <= 3; i++) {
int moveY = curPos.y + dy[i];
int moveX = curPos.x + dx[i];
if (!(moveY < n && moveX < n && moveY >= 0 && moveX >= 0)) continue;
if (visited[moveY][moveX]) continue;
visited[moveY][moveX] = true;
if (map[moveY][moveX] <= sharkSize)
q.add(new Pos(moveY, moveX, curPos.distance + 1));
}
if (q.peek() != null) {
Pos peek = q.peek();
if (map[peek.y][peek.x] < sharkSize && map[peek.y][peek.x] > 0) {
// 큐에 담긴 pos에 있는 물고기가 상어보다 작으면 물고기를 먹는다
eatCnt++;
if (eatCnt == sharkSize) {
sharkSize++;
eatCnt = 0;
}
map[peek.y][peek.x] = 0;
// 큐를 비우고 상어를 peek 위치로 이동
q.clear();
q.add(new Pos(peek.y, peek.x, 0));
answer += peek.distance;
visited = new boolean[n][n];
visited[peek.y][peek.x] = true;
}
}
}
System.out.println(answer);
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 15684번 / Java / 사다리 조작 - DFS, 시뮬레이션, 완전탐색 풀이 (0) | 2020.06.08 |
---|---|
[백준] 16234번 / Java / 인구 이동 (0) | 2020.06.07 |
[백준] 17144 / Java / 미세먼지 안녕! - 시뮬레이션 (0) | 2020.05.26 |
[백준] 15683번 / Java / 감시 - 완전탐색 (0) | 2020.05.21 |
[백준] 14889번 / Java / 스타트와 링크 - 재귀풀이 (0) | 2020.05.20 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 완전탐색
- 백준
- 큰 수 만들기
- java
- 인구이동
- 사다리 조작
- 브라우저 요청
- 구현
- withCredentials
- Access-Control-Allow-Origin
- 아기상어
- 프로그래머스
- 드래곤 커브
- 우선순위큐
- 14891
- Greedy
- dfs
- 그리디
- header
- 코딩테스트 연습
- 구명보트
- 16234
- BOJ
- 재귀
- 코테
- 코딩테스트
- 배열순회
- 시뮬레이션
- 자바
- 톱니바퀴
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함