알고리즘/Python

[백준] 16236 - 아기상어

9__bin 2023. 9. 3. 19:52

https://www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

문제 한줄 이해

- N*N격자에 아기상어와 물고기가 있을 때 문제에서 주어진 조건에 맞춰 엄마상어를 부르기 전까지의 시간을 구하기

생각난 풀이

문제를 읽고 생각난 필요한 조건들

문제가 길기도 했고 필요한 조건들이 많다고 생각이 들었다. -> 다행히 문제풀이에 필요한 조건 뽑기 연습을 하고 있어서 다행이다!!

1. 아기상어를 기준으로 각 물고기들까지의 거리를 구하기

-> 아기상어의 위치를 기준으로 현재 공격 가능한 물고기 위치와 거리 저장할 배열 필요

 

2. 거리가 가까운순으로 먼저 잡고 거리가 같다면 맨위, 맨왼쪽 순으로 물고기 잡아먹기

-> 1번에서 구한 물고기 배열을 정렬하기 why? 먼저 거리가 가까워야 하므로 거리를 기준으로 정렬 -> 맨위 맨왼쪽이라는 뜻은 결국 2차원 배열에서 격자 위치가 0,0에 가까울수록 맨위, 맨왼쪽 이기에!!!

 

3. 자기 공격포인트만큼 잡아먹으면 레벨업!

-> 잡아먹은 횟수 저장

import sys
from collections import deque
n = int(sys.stdin.readline())
graph = []

for i in range(n):
    graph.append(list(map(int,sys.stdin.readline().split())))

def dfs(x,y):
    que = deque()
    que.append((x,y))
    dx = [0,-1,0,1]
    dy = [-1,-0,1,0]
    #방문처리
    visited = [[0 for i in range(n)] for i in range(n)]
    #공격가능한 물고기 위치까지의 거리를 저장하기 위해
    dis  = [[0 for i in range(n)] for i in range(n)]
    
    visited[x][y] = 1
    #공격 가능한 물고기의 위치와 거리 저장하기 위해
    fish = []
    
    while que:
        nowx, nowy = que.popleft()
        
        for i in range(4):
            nextx = nowx + dx[i]
            nexty = nowy + dy[i]
            
            if nextx >=0 and nexty >=0 and nextx<n and nexty<n:
            	# 공격포인트보다 낮거나 같으면 '이동'이 가능
                if graph[nextx][nexty] <= attack and visited[nextx][nexty] == 0:
                    visited[nextx][nexty] = 1
                    dis[nextx][nexty] = dis[nowx][nowy] + 1
                    que.append((nextx,nexty))
                    # 공격포인트보다 낮은 물고라면 '공격'이 가능
                    if 0 < graph[nextx][nexty] and graph[nextx][nexty] < attack:
                        fish.append((nextx,nexty,dis[nextx][nexty]))
    
    # 따라서 물고기 배열을 먼저 거리를 기준으로 정렬 -> 맨위이므로 x[0]을 기준으로 정렬-> 맨왼쪽 x[1]
    return sorted(fish, key = lambda x: (x[2],x[0],x[1]))

# 아기상어 위치 구하고 기본 공격포인트와 잡아먹은 횟수 선언
for i in range(n):
    for j in range(n):
        if graph[i][j] == 9:
            startx = i
            starty = j
attack = 2
cnt = 0
ans = 0


while True:
	#공격 가능한 물고기 배열을 큐로 받기 why? 맨앞에 정렬된 것을 뽑기위해
    possible = deque(dfs(startx,starty))
    
    #더 이상 공격할 수 없으므로 엄마상어 불러야 한다.
    if len(possible) == 0:
        break

	#공격 가능한 좌표와 거리
    nextx,nexty,dis = possible.popleft()
    
    #이미 구해둔 거리가 즉 걸리는 시간
    ans = ans + dis
    
    #이전 위치는 아기상어가 있던 자리이므로 0으로
    graph[startx][starty] = 0
    #다음 위치도 잡아먹을거기 때문에 0
    graph[nextx][nexty] = 0
    #현재 위치를 다음위치로 바꾸기
    startx, starty = nextx,nexty
    
    # 잡아먹은 횟수 계산해서 공격포인트랑 같으면 레벨업!
    cnt +=1
    if cnt == attack:
        attack +=1
        cnt = 0
print(ans)

'알고리즘 > Python' 카테고리의 다른 글

[백준] 27172 - 수 나누기 게임  (0) 2023.09.12
[백준] 2467 - 용액  (0) 2023.09.11
[백준] 11779 - 최소비용 구하기 2  (0) 2023.09.02
[백준] 2638 - 치즈  (0) 2023.09.01
[백준] 1238 - 파티  (0) 2023.08.28