김호쭈
DevForYou
김호쭈
전체 방문자
오늘
어제
  • 분류 전체보기 (321)
    • • 데이터베이스(DB) (9)
      • __SQL__ (9)
    • •알고리즘(Algorithm ) (117)
      • 문제풀이 (99)
      • 스터디 (14)
      • 알고리즘 팁 (4)
    • •Compter Science (57)
      • Operating System (25)
      • Computer Network (1)
      • Computer Vision (16)
      • Artificial Intelligence (14)
      • Software Technology (1)
    • • 독서 (36)
      • Design Pattern (24)
      • 객체지향의 사실과 오해 (1)
      • Object Oriented Software En.. (11)
    • • 개발 (26)
      • React (3)
      • node.js (6)
      • Django (11)
      • Spring boot (6)
    • • 개발Tip (4)
      • GitHub (0)
    • •프로젝트 (2)
      • 물물 (2)
    • •App (54)
      • 안드로이드 with Kotlin (50)
      • 코틀린(Kotiln) (4)
    • •회고 (8)
    • •취준일기 (3)
    • • 기타 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • GitHubDesktop
  • 깃허브데스크탑
  • ㄱ
  • 로컬저장소
  • 원격저장소
  • KMU_WINK
  • Remote저장소
  • local저장소

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
김호쭈

DevForYou

•알고리즘(Algorithm )/문제풀이

[백준16236&파이썬] BFS을 작은단위로 쪼개 생각하자. 종료조건과 탐색조건을 잘 생각하자.

2023. 4. 26. 15:08

# 문제

백준 16236 아기상어 파이썬 풀이

 

16236번: 아기 상어

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

www.acmicpc.net

# 코드

'''
  - BFS 단위를 잘 쪼개자. BFS를 소규모 단위로 쪼개서 끝내버릴 수록 코드짜기가 수월한거 같다.
  - BFS 에서 상태단위를 관리하기 위해서는, 큐에 담아서 뽑아서 계속 유지하고 업데이트 해야한다.
  - 이동한 경로를 0으로 표기해주자
  - 최소값 단위로 뽑아쓴다면 heap을 쓰면 더 빠를거 같다. 물고기 관리하는 fish배열을 heap으로 관리해볼까?
'''
import sys
from collections import deque


def print2D(arr):
  for row in range(N):
    for col in range(N):
      print(arr[row][col], end=" ")
    print()
  print()


N = int(sys.stdin.readline().strip())  # 공간의 크기
board = list()

dirs = [
  (-1, 0), (0, -1), (1, 0), (0, 1)
  ]

for _ in range(N):
  line = list(map(int, sys.stdin.readline().split()))
  board.append(line)

# 물고기통을 기준으로 한다
# 현재 시작점에서 BFS로 물고기 후보들을 구한다
# 구한 물고기 후보들에서 가장 거리가 가까운 순에서 맨위 맨 왼쪽에 있는 물고기를 첫번째로 꺼낸다
# 다시 탐색하고 물고기 후보가 없어지면 탐색을 종료한다.

start = (-1, -1)
for row in range(N):
  for col in range(N):
    if board[row][col] == 9:
      start = (0, row, col)  # 거리, 행, 열

fishes = list()
sstate = (2, 0, 0)  # ( 몸집, 먹은 물고기 수 , 이동한 칸 )
fishes.append((start, sstate))  # (거리, 행, 열), ( 몸집, 먹은 물고기 수 , 이동한 칸 )
total = 0
while len(fishes) != 0:
  fishes.sort(key=lambda x: (x[0][0], x[0][1], x[0][2]))  # 거리, 위치 순으로 정렬한다
  time, row, col = fishes[0][0]
  total += time
  state = fishes[0][1]
  fishes.clear()  # 물고기후보군 비우기
  cur = (row, col)
  visit = [[False] * N for _ in range(N)]
  visit[cur[0]][cur[1]] = True  # 방문처리
  board[cur[0]][cur[1]] = 0  # 시작점 초기화

  dq = deque()
  dq.append((cur[0], cur[1], 0))  # 행,열, 시작점에서부터 거리

  while len(dq) != 0:
    pos = dq.popleft()  # 현재 위치부터 BFS로 전역 탐색함
    for dir in dirs:
      next = (pos[0] + dir[0], pos[1] + dir[1])
      if 0 <= next[0] < N and 0 <= next[1] < N and not visit[next[0]][next[1]]:  # 범위 안이면서 방문하지 않은 곳이면

        if board[next[0]][next[1]] == 0 or board[next[0]][next[1]] == state[0]:  # 그냥 이동이 가능한 곳이면
          dq.append((next[0], next[1], pos[2] + 1))
          visit[next[0]][next[1]] = True  # 방문처리

        elif 0 < board[next[0]][next[1]] < state[0]:  # 먹을 수 있는 후보군 이면
          level = state[0]
          eatten = state[1] + 1
          if level == eatten:
            level += 1
            eatten = 0
          fishes.append(((pos[2] + 1, next[0], next[1]), (level, eatten, 0)))
          visit[next[0]][next[1]] = True
print(total)


## -- 고민했던 조건 들 -- ##
# # 종료조건
# # 상어가 더이상 먹을 물고기가 없으면 종료되어야함
# # 이걸 탐색으로 스스로 종료되게 할지 ?
# # 탐색 시작전에 딕셔너리에서 자기 아래것들의 숫자를 돌려서 찾을지 ?
# # 탐색조건
# # 거리가 가까운 물고기라면, 가장 위에 있는 그다음으로는 가장 왼쪽에 있는 물고기를 먼저 먹는다.
# # 가장 가까운 위에서부터 먹고 같으면 왼쪽부터 먹는다는 표현이 이해가 잘 안간다.
# # BFS로 이동순서를 정의해주는게 아닌가?
# # 우선순위를 줘야한다.
#
# # BFS를 매턴마다 돌리자
# # 턴은 물고기를 먹을때

# 풀이

  • 문제의 핵심 풀이 전략은 BFS를 돌려서 먹을 물고기가 선택됐다면 해당 위치에서 방문상태와 board를 초기화 하고 다시 시작하는 것이다.
  • 물고기를 선택할때에는 dirs배열로 알아서 우선순위가 정해지는 것이 아닌, 물고기 후보군들을 만들고 후보군들 중에서가 현재 위치와 거리가 가장 가까우며 가장 위쪽이면서 가장 오른쪽일때를 만족하는 첫번째 물고기를 선택하면 된다. (정렬로 해결 할 수 있다. )
  • 문제를 풀기 위해서 종료조건과 탐색조건에 대해서 고민을 해봐야하며 이 방법에 대한 접근이 맞았다면 물고기를 선택하는 방법을 조금더 고민해봐야한다.
  • BFS단위를 잘 쪼개 써야 함을 알 수 있는 문제였다. 가장 작은 단위에서의 BFS의 역할과 책임을 정한다면 헷갈리지 않을 것이다. 
  • fish를 뽑을때 heap을 사용해보는 것도 생각해보면 좋을거 같다.
저작자표시 (새창열림)

'•알고리즘(Algorithm ) > 문제풀이' 카테고리의 다른 글

[백준2512&파이썬] 이분탐색은 YES or NO인지 묻는 것이다.  (0) 2023.04.28
[백준1939&파이썬] 이진탐색 BFS에 응용하기, 이진탐색 경계값 설정에 주의하자.  (0) 2023.04.27
[백준6497&파이썬] 크루스칼은 최소신장트리를 구할 수 있다.  (0) 2023.04.26
[백준1647&파이썬] 크루스칼 알고리즘을 이용한다면 최소신장트리(MST)를 찾을 수 있다.  (0) 2023.04.26
[백준1956&파이썬] 플로이드-와샬을 이용해 왕복 최단거리를 찾아보자  (0) 2023.04.25
    '•알고리즘(Algorithm )/문제풀이' 카테고리의 다른 글
    • [백준2512&파이썬] 이분탐색은 YES or NO인지 묻는 것이다.
    • [백준1939&파이썬] 이진탐색 BFS에 응용하기, 이진탐색 경계값 설정에 주의하자.
    • [백준6497&파이썬] 크루스칼은 최소신장트리를 구할 수 있다.
    • [백준1647&파이썬] 크루스칼 알고리즘을 이용한다면 최소신장트리(MST)를 찾을 수 있다.
    김호쭈
    김호쭈
    공부하고 정리하고 기록하기

    티스토리툴바