Python3/백준 알고리즘

2022.05.17 [백준] (python 파이썬) 아기 상어

ian's coding 2022. 5. 17. 17:35
728x90
반응형

 

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

 

16236번: 아기 상어

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

www.acmicpc.net


풀이

이 문제는 BFS를 사용하면 되는 문제이지만 물고기를 먹을 때마다 BFS를 해야 한다.

이유는 물고기를 먹을때마다 다음에 먹을 물고기의 최단거리를 구해야 하기 때문이다.

우선

shark_x,shark_y=0,0 # 상어의 위치
shark_size=2 # 상어의 크기
eat_cnt=0 # 상어가 먹은 물고기 수
fish_cnt=0 # 물고기 수
time=0

변수들을 선언해주었다.

이후 각 N*N크기의 데이터를 입력받았다.

이때 각 라인을 입력받을 때마다 해당 라인에 9가 있는지 확인했다. 만약 9가 있으면 shark_x, shark_y의 값을 해당 좌표로 저장했다. 입력을 모두 받고 다시 탐색하면 시간이 오래 걸릴거같아 입력받을 때마다 해당 라인을 확인했다.

또 입력받은 값이 0보다 크고 6보다 작거나 같으면 물고기가 있다는 말이기 때문에 fish_cnt를 증가시켰다.

BFS함수에서 방문여부를 체크할 vis배열을 선언후 deque에 현재 상어의 위치와 이동거리를 넣고 min_dis를 최대사이즈로 선언했다. 이유는 만약 탐색하다가 상어가 먹을 수 있는 물고기가 나오면 해당 물고기까지의 거리를 min_dis에 저장 후, min_dis보다 크면 덱에 추가하지 않기 위해서이다.

그리고 탐색을 하며 최단거리의 물고기를 찾고 fish_list에 좌표와 거리를 저장한다.

그리고 내림차순 정렬하여 가장 위에 있고 왼쪽에 있는 최단거리의 먹을 수 있는 물고기를 반환한다.

그리고 eat_cnt를 증가시키고 만약 shark_size와 eat_cnt가 같으면 shark_size를 증가시킨 후, eat_cnt를 0으로 초기화 시켜준다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import sys
from collections import deque
 
N=int(input())
arr=[]
 
shark_x,shark_y=0,0 # 상어의 위치
shark_size=2 # 상어의 크기
eat_cnt=0 # 상어가 먹은 물고기 수
fish_cnt=0 # 물고기 수
time=0
 
dx=[0,0,1,-1]
dy=[1,-1,0,0]
 
for i in range(N):
    arr.append(list(map(int,input().split())))
    for j in range(N):
        # 상어의 좌표 저장
        if arr[i][j]==9:
            shark_x,shark_y=i,j
            arr[i][j]=0
        #물고기의 갯수 카운팅
        elif 0<arr[i][j]<=6:
            fish_cnt+=1
 
def BFS(shark_x,shark_y):
    vis = [[False for _ in range(N)] for _ in range(N)]
    deq=deque()
    deq.append([shark_x,shark_y,0])
    vis[shark_x][shark_y]=True
    #먹을 수 있는 물고기까지의 최단거리 저장할 변수
    min_dis=sys.maxsize
    #물고기의 좌표와 거리 저장
    fish_list=[]
    while deq:
        x,y,dis=deq.popleft()
        for i in range(4):
            nx=x+dx[i]
            ny=y+dy[i]
            if 0<=nx<and 0<=ny<and not vis[nx][ny]:
                #이동할 곳이 shark_size보다 작거나 같으면 이동할 수 있으므로 
                #해당 좌표의 vis배열 True로 변경
                if arr[nx][ny]<=shark_size:
                    vis[nx][ny]=True
                    #이동한 곳이 0보다 크고 shark_size보다 작으면 먹을 수 있는
                    #물고기이므로 min_dis에 이동거리 저장
                    if 0<arr[nx][ny]<shark_size:
                        #이동거리가 min_dis보다 크면 최단거리가 아니기 때문에 pass
                        if min_dis>=dis+1:
                            min_dis=dis+1
                            #최단거리의 물고기 좌표, 거리 저장
                            fish_list.append((nx,ny,dis+1))
                    #이동할 좌표의 값이 0이고 이동거리가 min_dis보다 작으면 아직 
                    #먹을 수 있는 물고기를 찾지 못했기 때문에 deq에 해당 좌표,거리 저장
                    if dis+1<min_dis:
                        deq.append([nx,ny,dis+1])
    #만약 fish_list에 데이터가 들어있으면 최단거리에 먹을 수 있는
    #물고기를 찾았기 때문에 해당 배열을 내림차순 정렬해준다.
    #(내림차순 정렬하면 x좌표가 작은 순, 만약 같으면 y좌표가 작은순으로 저장됨)
    #이때 이동거리는 모두 최단거리만 저장되어 따로 정렬에 영향을 끼치지 않음
    if fish_list:
        fish_list.sort()
        print(fish_list)
        #가장 위에 있고 가장 왼쪽에 있는 최단거리의 먹을 수 있는 물고기를 반환
        return fish_list[0]
    else:
        return False
 
 
 
while fish_cnt:
    result=BFS(shark_x,shark_y)
    if not result:
        break
    shark_x,shark_y=result[0],result[1]
    time+=result[2]
    eat_cnt+=1
    fish_cnt-=1
    if shark_size==eat_cnt:
        shark_size+=1
        eat_cnt=0
    arr[shark_x][shark_y]=0
 
print(time)
 
 
cs

 

 

 

728x90
반응형