백준 알고리즘/Problems
[BOJ/16236] 아기 상어 - 풀이 및 코드
highlaw00
2023. 8. 26. 00:41
16236번: 아기 상어
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가
www.acmicpc.net
문제
풀이
구현 문제로, 요구사항을 정리하면 다음과 같습니다.
아기 상어는 먹을 수 있는 물고기가 없으면 프로그램을 종료하고 정답을 출력한다.
정답은 아기 상어가 물고기를 먹으며 소모한 시간(초)이다.
아기 상어가 먹을 수 있는 물고기를 찾는 방법은 다음과 같다.
1. 현재 아기 상어의 위치에서 BFS를 진행한다.
2. BFS를 진행하며 아기 상어의 크기보다 큰 물고기는 통과할 수 없다. (큐에 삽입 X)
3. BFS를 진행하며 아기 상어의 크기보다 작거나 같은 물고기는 거리를 표시해둔다. (거리 갱신 및 큐 삽입)
4. 위 BFS 결과에서 가장 거리가 가까운 물고기를 골라 거리만큼 정답을 증가시키고 아기 상어의 위치를 그 물고기의 위치로 바꾼다.
5. 위 BFS 결과에서 먹을 수 있는 물고기가 없다면 프로그램을 종료한다.
로직은 굉장히 단순합니다. BFS를 진행하여 먹을 수 있는 물고기를 식별하고 그 중 거리가 가장 가까우며 좌표가 좌상단에 가까운 물고기를 골라 해당 위치로 가는 비용을 정답에 계속 더해가면 되는 문제입니다. 하지만 신경써야할 것이 꽤 많은데 다음과 같은 것들을 신경써서 코드를 작성하면 큰 어려움 없이 문제를 푸실 수 있습니다.
1. 먹은 물고기는 더이상 먹으면 안된다. 따라서 그것을 식별할 정보가 필요하다.
2. 물고기를 먹은 뒤 해당 위치로 이동한다. 따라서 BFS를 진행할 때 시작 위치가 계속 바뀐다.
3. 물고기를 먹은 뒤 먹은 물고기의 개수가 현재 물고기의 크기와 같아지면 상어의 크기가 1씩 커진다.
위 주의사항을 잘 지키며 구현해내면 큰 무리없이 풀 수 있다.
코드
BOJ 코드 치팅은 제재 대상입니다.
더보기
import sys
from collections import deque
input = sys.stdin.readline
INT_MAX = sys.maxsize
n = int(input().rstrip())
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
dirs = ((1, 0), (-1, 0), (0, 1), (0, -1))
# 최초의 상어 위치 및 물고기 정보 기록
r, c = 0, 0
for i in range(n):
flag = False
for j in range(n):
if grid[i][j] == 9:
r, c = i, j
grid[i][j] = 0
flag = False
break
if flag:
break
def bfs(r, c):
global dists, visited, curr_size, eatable_fishes, eaten_fishes
q = deque()
q.append((r, c))
cost = 0
while q:
cost += 1
for _ in range(len(q)):
i, j = q.popleft()
for di, dj in dirs:
ni, nj = i + di, j + dj
if ni < 0 or nj < 0 or ni >= n or nj >= n:
continue
# 자신보다 작거나 같으면 통과 가능
if not visited[ni][nj] and curr_size >= grid[ni][nj]:
visited[ni][nj] = True
dists[ni][nj] = cost
q.append((ni, nj))
# 먹지 않았으며 먹을 수 있다면 기록
if grid[ni][nj] != 0 and curr_size > grid[ni][nj] and (ni, nj) not in eaten_fishes:
eatable_fishes.append((cost, (ni, nj)))
ans = 0
ate_cnt = 0
curr_size = 2
eaten_fishes = set()
while True:
# 상어 위치에서 BFS 진행하여 물고기 정보 갱신
visited = [[False for _ in range(n)] for _ in range(n)]
dists = [[INT_MAX for _ in range(n)] for _ in range(n)]
visited[r][c] = True
dists[r][c] = 0
eatable_fishes = []
bfs(r, c)
# 먹을 수 있는 물고기를 오름차순 정렬 (비용, row, column)
eatable_fishes.sort(key=lambda x: [x[0], x[1][0], x[1][1]])
if eatable_fishes:
cost, location = eatable_fishes[0]
i, j = location
ans += cost
ate_cnt += 1
eaten_fishes.add((i, j))
r, c = i, j
else:
break
# 섭취 후 크기 증가
if ate_cnt == curr_size:
curr_size += 1
ate_cnt = 0
print(ans)
참고자료
https://highlaw00-dev.tistory.com/36
[알고리즘] 시뮬레이션 - dx, dy 기법
목표 시뮬레이션 문제를 해결할 때 사용할 수 있는 dx, dy 기법이 무엇인지 알아본다. 과정 시뮬레이션 문제란? 시뮬레이션 문제는 주어진 문제의 조건을 구현하여 원하는 정답을 찾는 문제이다.
highlaw00-dev.tistory.com
좌표계 문제를 풀 때 용이한 dx, dy 기법을 포스팅 해두었습니다.