김호쭈
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
  • 로컬저장소
  • 원격저장소
  • 깃허브데스크탑
  • local저장소
  • ㄱ
  • Remote저장소

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
김호쭈

DevForYou

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

[백준16932&파이썬] BFS/DFS풀이에서 시간초과가 난다면 전처리방법이 있는지 고민해라

2023. 4. 16. 02:21

# 문제

백준 16932 모양만들기 파이썬 풀이

 

16932번: 모양 만들기

N×M인 배열에서 모양을 찾으려고 한다. 배열의 각 칸에는 0과 1 중의 하나가 들어있다. 두 칸이 서로 변을 공유할때, 두 칸을 인접하다고 한다. 1이 들어 있는 인접한 칸끼리 연결했을 때, 각각의

www.acmicpc.net

# 코드

## 성공한 풀이

import sys
from collections import deque

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

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

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


# 1 모양들 부분집합들의 크기를 미리 구해서 memo에 추가해놓는다
# 위치기록용 스택을 활용한다.
# 0에서 돌려서 memo를 활용한다
memo = [ [-1] * M for _ in range(N)]
number = 0
for row in range(N) :
  for col in range(M) :
    if board[row][col] == 1 and memo[row][col] == -1 : # 한번도 들린곳이 아니기 때문에 루틴을 수행한다.
      cnt = 1
      cur = (row, col)
      stk = deque()
      dq = deque()
      dq.append(cur)
      stk.append(cur)
      memo[row][col] = True

      while len(dq) != 0:
        now_cur = dq.popleft()

        for dir in dirs :
          next = (now_cur[0] + dir[0], now_cur[1] + dir[1])
          if 0 <= next[0] < N and 0<= next[1] < M : # 범위 안에 있고
            if memo[next[0]][next[1]] != True and board[next[0]][next[1]] == 1: # 방문했던 곳이 아니라면
              cnt +=1
              dq.append(next)
              stk.append(next)
              memo[next[0]][next[1]] = True

      while len(stk) != 0:
        now_cur = stk.pop()
        memo[now_cur[0]][now_cur[1]] = (cnt,number)
      number+=1
# print(memo)

mmax = 0
for row in range(N) :
  for col in range(M) :
    if board[row][col] == 0 :
      candidate = set()
      sum = 1
      for dir in dirs : # 4방향 돌려
        next = (row + dir[0], col + dir[1])

        if 0 <= next[0] < N and 0<= next[1] < M : # 범위 안이면
          if memo[next[0]][next[1]] != -1 :
            poped = memo[next[0]][next[1]]
            if poped[1] not in candidate : # 포함되지 않았으면
              candidate.add(poped[1])
              sum+=poped[0]
      mmax = max(mmax,sum)

print(mmax)

## 실패한 풀이( 시간초과)

###--- BFS를 이용하는 풀이 시간초과 ---###
mmax = 0
# 0인곳에서 시작해서, 0의 모양을 1로 바꾸고, 최대값을 구한다.
for row in range(N) :
  for col in range(M) :
    if board[row][col] == 0 :
      visit = [ [False] * M for _ in range(N)]

      dq = deque()
      dq.append((row,col))
      visit[row][col] = True

      cnt = 1
      while len(dq) != 0 :
        cur = dq.popleft()

        for dir in dirs :
          next = (cur[0] + dir[0], cur[1] + dir[1])
          if 0<= next[0] < N and 0<= next[1] < M : # 범위 안이라면
            if visit[next[0]][next[1]] == False and board[next[0]][next[1]] == 1: # 방문하지 않았다면
              dq.append(next) # 큐어 넣어주기
              visit[next[0]][next[1]] = True # 방문처리
              cnt +=1

      mmax = max(mmax,cnt)

print(mmax)

# 풀이

  • 시간초과를 염두해라, 반복문으로 모든 0인지점을 시작점으로 1로 바꿔서 최대크기를 찾는 풀이는 시간초과가 났다.
  • 이걸 해결하기 위해서 모양들의 그룹을 나누고 그룹의 크기와 번호를 지정했다. 이 전처리과정을 끝내고 0인지점에서부터 4방향 탐색으로 다른 그룹들의 크기의 합을 구해서 최대값을 찾는 방식으로 문제에 접근했다.
  • 그룹을 매기는 과정을 스택을 활용해서 memo 배열에 최신화 시켰다. 여기에는 그룹의 크기와 그룹번호가 들어갔다.
  • 굳이 스택까지 안쓰고, 그룹의 번호를 매기고 그룹의 크기만 따로 저장해서 사용하면 시간을 더 줄일 수 있을거 같다.
  • 어쩌다보니 이 문제를 해결하려고 했던 계기가, 시간초과 -> DP를 이용할 수 있는지였는데, DP를 적용시킬 수 있는 방법을 찾다가 위와 같은 전처리 방법을 발견했다.
  • 또한 파이썬의 set은 O(1)의 속도로 찾을 수 있다고 하니 활용하면 좋을듯 싶다
    • if 찾을 숫자 not in SET
저작자표시 (새창열림)

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

[백준2251&파이썬] BFS는 가지치기로 경우의 수를 구하기 적합하며 방문처리의 방법을 생각해보자  (0) 2023.04.17
[백준4803&파이썬] BFS를 활용하여 사이클을 찾아 트리여부를 확인하자  (0) 2023.04.16
[백준1325&파이썬] DFS+DP는 사이클이 없을때 사용 가능하다.  (0) 2023.04.15
[백준2644&파이썬] 재귀식을 이용한 DFS 사용할때는 실패케이스에 대한 반환값을 생각하자  (0) 2023.04.15
[백준11725&파이썬] BFS와 DFS에서 그래프 인접리스트의 활용  (1) 2023.04.15
    '•알고리즘(Algorithm )/문제풀이' 카테고리의 다른 글
    • [백준2251&파이썬] BFS는 가지치기로 경우의 수를 구하기 적합하며 방문처리의 방법을 생각해보자
    • [백준4803&파이썬] BFS를 활용하여 사이클을 찾아 트리여부를 확인하자
    • [백준1325&파이썬] DFS+DP는 사이클이 없을때 사용 가능하다.
    • [백준2644&파이썬] 재귀식을 이용한 DFS 사용할때는 실패케이스에 대한 반환값을 생각하자
    김호쭈
    김호쭈
    공부하고 정리하고 기록하기

    티스토리툴바