김호쭈
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
  • 로컬저장소
  • Remote저장소
  • KMU_WINK
  • 원격저장소
  • local저장소

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
김호쭈

DevForYou

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

[백준2638&파이썬] BFS에 구현과 시뮬레이션이 섞인 문제

2023. 5. 11. 00:01

# 문제

백준 2638 치즈 파이썬 풀이

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

# 코드

import sys
from collections import deque

def show2D(arr):
  for i in range(len(arr)):
    print(*board[i])

N, M = map(int, sys.stdin.readline().split())
board = list()

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

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

# 치즈의 외곽과 치즈의 외부를 어떻게 구별할 것인가?
  # 내부공기인지의 여부..를 어떻게 알 수 있을까?
  # 해당 좌표에서 4방향을 찍고 내부인지 외부인지 판단해야 할듯
  # 가장자리에는 치즈가 놓이지 않는다. 가장자리는 무조건적으로 외곽이지 않을까? <- 채택
# 동시에 없애야한다.
  # 하나씩 순차적으로 체크하고 없애버리면 영향을 끼치게 된다.
  # 매 탐색 시작시 마다 내 외부를 결정해야하는데.. 이 방법이 맞을까 싶다.

timer = 0
while True:
  # board[0][0]으로 완전탐색 한번 돌려버리고 외곽 외곽은 -1, 내부는 0으로 마킹하자
  dq = deque()
  dq.append((0, 0))  # 첫 가장자리
  end_cnt = 1  # 이게 N*M 되면 종료조건임 ( 모든곳이 다 외곽이라는 뜻 )
  board[0][0] = -1  # 방문표시

  while len(dq) != 0:
    row, col = dq.popleft()
    for dir in dirs:
      next_row = row + dir[0]
      next_col = col + dir[1]
      if 0 <= next_row < N and 0 <= next_col < M:
        if board[next_row][next_col] == 0:  # 치즈 있는 곳이 아니라면
          board[next_row][next_col] = -1  # 방문표시
          dq.append((next_row, next_col))
          end_cnt += 1

  if end_cnt == N * M:  # 모든곳이 다 외곽이기 때문에 종료조건이 된다.
    break

  # 치즈를 녹인다.
  for row in range(N) :
    for col in range(M) :
      if board[row][col] == 1 :
        air_cnt = 0
        for dir in dirs :
          next_row = row + dir[0]
          next_col = col + dir[1]
          if 0<= next_row < N and 0<= next_col < M :
            if board[next_row][next_col] == -1 : # 외부 공기이면
              air_cnt+=1

        if 2<= air_cnt : # 접촉 외부 공기가 2이상일때
          candidaties.append((row,col))

  # 후보군에서 뽑아서 그 자리를 0으로 만든다. ( 치즈를 녹이를걸 후행시키기 위해서 )
  for candidate in candidaties :
    board[candidate[0]][candidate[1]] = 0

  # 다시 원상복귀를 시킨다.
  for row in range(N):
    for col in range(M):
      if board[row][col] == -1:
        board[row][col] = 0
  timer += 1
  candidaties.clear()

print(timer)

# 풀이

  • 그래프 탐색을 이용해서 외곽공기와 두곳이상 닿아있는곳을 구하면 된다. 저번에도 유사한 문제를 풀었었는데, 녹을 치즈가 결정되면 그자리에서 녹이면 안된다. 나름의 동시성(?)문제가 생긴다.
  • 같은 시간대이지만 반복문으로 그자리에서 녹여버리면 그 옆 치즈가 영향을 받게 된다. 그렇기 때문에 녹일 치즈를 한곳(리스트)에 담아두고, 한번에 그 치즈들을 녹여 board를 업데이트 해줘야한다.
  • 위의 내용까지는 아주 쉽다. 그러나 외곽공기와 내부공기를 판별하기 위해서 계속 생각을 해봤다. 
  • 왼쪽이나 오른쪽으로 선을 쫙 그어서 다각형의 내외부르 판단해볼까 했었다. ( 이건 아닌거 같아서 안함 )
  • 문제를 자세히 읽어보니 가장자리에는 항상 치즈가 놓일 수 없다는 조건이 있었다. 그렇기 때문에 ( 0, 0 )은 항상 외곽공기가 될 것이다. 그러면 그 공기로부터 그래프탐색(BFS)를 돌리면 모든 외곽공기를 알 수 있게 된다.
  • 외곽공기를 -1로 마킹하고, 녹일 치즈를 선택하도록 코드를 작성했다. 
  • 무엇보다 시간초과 날거 같았는데 안나는게 신기했다. 

 

저작자표시 (새창열림)

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

[백준12851&파이썬] BFS를 이용해 최단시간 도착과 최단시간의 모든경우의 수를 구하자  (0) 2023.05.13
[백준13549&파이썬] BFS에서 큐에 넣을때 때때로 순서도 중요하다.  (1) 2023.05.11
[백준1932&파이썬] DP를 이용할때 확정지을 노드를 선택하는 기준과 근거가 필요하다.  (0) 2023.05.09
[백준9465&파이썬] DP를 풀때는 N이 1일때부터 하나씩 늘려가며 경우의 수를 따져보자.  (0) 2023.05.09
[백준1149&파이썬] DP를 사용할때 확정되는 값에 대한 명확한 근거를 찾자  (1) 2023.05.08
    '•알고리즘(Algorithm )/문제풀이' 카테고리의 다른 글
    • [백준12851&파이썬] BFS를 이용해 최단시간 도착과 최단시간의 모든경우의 수를 구하자
    • [백준13549&파이썬] BFS에서 큐에 넣을때 때때로 순서도 중요하다.
    • [백준1932&파이썬] DP를 이용할때 확정지을 노드를 선택하는 기준과 근거가 필요하다.
    • [백준9465&파이썬] DP를 풀때는 N이 1일때부터 하나씩 늘려가며 경우의 수를 따져보자.
    김호쭈
    김호쭈
    공부하고 정리하고 기록하기

    티스토리툴바