|
| 1 | +# 백준 16236번: 아기 상어 (3회차) |
| 2 | + |
| 3 | +from collections import deque |
| 4 | +import sys |
| 5 | + |
| 6 | +input = sys.stdin.readline |
| 7 | + |
| 8 | +# N <= 20 |
| 9 | +N = int(input()) |
| 10 | +maps = [list(map(int, input().rstrip().split())) for _ in range(N)] |
| 11 | + |
| 12 | +# 포인트 |
| 13 | +# 1. 아기 상어는 자신과 작거나 같은 경우 지나칠 수 있음 |
| 14 | +# 2. 아기 상어는 자신과 작은 경우 먹을 수 있음 |
| 15 | +# 3. 아기 상어는 먹을 수 있는 먹이 중에서는 가장 가까운 먹이를 먹음 |
| 16 | +# 4. 가장 가까운 먹이가 여러 개라면, Z 순서로 먹이를 먹음 |
| 17 | +# 5. 먹을 수만 있다면, 크기가 더 작느냐는 중요치 않고 거리가 중요하다는 점 명심 |
| 18 | +# 6. 이 때의 거리는 유클리디안 거리가 아닌, BFS 이동 거리라는 점 명심 |
| 19 | +# 아이디어 |
| 20 | +# 1. 현재 아기 상어로부터 BFS 수행, 먹을 수 있는 먹이 후보를 모두 선정 -> O(N^2) |
| 21 | +# 2. 먹을 수 있는 먹이 후보 중 가장 좌상에 있는 먹이를 먹음 -> O(N^2) |
| 22 | +# 3. 이 과정을 모든 먹이 개수만큼 반복 -> O(N^2) |
| 23 | + |
| 24 | +moves = [ |
| 25 | + [0, 1], |
| 26 | + [0, -1], |
| 27 | + [1, 0], |
| 28 | + [-1, 0] |
| 29 | +] |
| 30 | + |
| 31 | +shark_r, shark_c = -1, -1 |
| 32 | +shark_size = 2 |
| 33 | +shark_eaten = 0 |
| 34 | +for r in range(N): |
| 35 | + for c in range(N): |
| 36 | + if maps[r][c] == 9: |
| 37 | + maps[r][c] = 0 |
| 38 | + shark_r, shark_c = r, c |
| 39 | + |
| 40 | +def is_in_board(r, c): |
| 41 | + return 0 <= r < N and 0 <= c < N |
| 42 | + |
| 43 | +def is_can_pass(r, c): |
| 44 | + global shark_size |
| 45 | + return maps[r][c] <= shark_size |
| 46 | + |
| 47 | +def is_can_eat(r, c): |
| 48 | + global shark_size |
| 49 | + return 1 <= maps[r][c] < shark_size |
| 50 | + |
| 51 | +def find_all_catchable_fishes(r, c): |
| 52 | + global shark_size |
| 53 | + q = deque() |
| 54 | + visited = [[404 for _ in range(N)] for _ in range(N)] |
| 55 | + candidates = [] |
| 56 | + |
| 57 | + q.append((r, c, 0)) |
| 58 | + visited[r][c] = 0 |
| 59 | + |
| 60 | + while q: |
| 61 | + r, c, moved = q.popleft() |
| 62 | + |
| 63 | + for dr, dc in moves: |
| 64 | + if is_in_board(r + dr, c + dc) and is_can_pass(r + dr, c + dc) and visited[r + dr][c + dc] > moved + 1: |
| 65 | + if is_can_eat(r + dr, c + dc): |
| 66 | + candidates.append((r + dr, c + dc, moved + 1)) |
| 67 | + visited[r + dr][c + dc] = moved + 1 |
| 68 | + else: |
| 69 | + q.append((r + dr, c + dc, moved + 1)) |
| 70 | + visited[r + dr][c + dc] = moved + 1 |
| 71 | + |
| 72 | + return candidates |
| 73 | + |
| 74 | +def find_one_fish_to_eat(candidates): |
| 75 | + candidates.sort(key=lambda x:(x[2], x[0], x[1])) |
| 76 | + return candidates[0] |
| 77 | + |
| 78 | +answer = 0 |
| 79 | +while True: |
| 80 | + candidates = find_all_catchable_fishes(shark_r, shark_c) |
| 81 | + # print(candidates) |
| 82 | + if len(candidates) == 0: break |
| 83 | + |
| 84 | + fr, fc, fmoved = find_one_fish_to_eat(candidates) |
| 85 | + # print(fr, fc, fmoved) |
| 86 | + maps[fr][fc] = 0 |
| 87 | + shark_r, shark_c = fr, fc |
| 88 | + answer += fmoved |
| 89 | + # print('---------------') |
| 90 | + # for row in maps: |
| 91 | + # print(row) |
| 92 | + # print('shark in', (shark_r, shark_c)) |
| 93 | + |
| 94 | + shark_eaten += 1 |
| 95 | + if shark_eaten >= shark_size: |
| 96 | + shark_size += 1 |
| 97 | + shark_eaten = 0 |
| 98 | + # print('shark size is', shark_size) |
| 99 | + |
| 100 | + # print('---------------') |
| 101 | + # print('answer:', answer) |
| 102 | + # print() |
| 103 | + |
| 104 | +print(answer) |
0 commit comments