Baekjoon/DFS와 BFS

🥇[백준] 2146 다리 만들기 (골드3) / BFS

2023. 5. 1. 14:52

문제요약

나의 코드 및 설명 (시간초과)

  • 처음 작성했던 코드.함수를 두개 만들어 하나는 섬을 구분하기 위한 bfs 함수, 하나는 거리정보를 구하기 위한 build_bridge 함수로 동작할 수 있도록 작성했다.
  • 함수를 두 개 활용해야 한다는 점은 잘 생각했으나, 메인 함수에서 모든 좌표를 방문하면서 build_bridge 함수를 수행한다는 것에서 시간이 너무 소요되었는지 시간초과가 발생했다.
from collections import deque

def build_bridge(sx,sy):
    global ans
    q = deque()
    q.append((sx,sy))
    while q:
        x,y = q.popleft()
        if v[y][x] != 0 and v[y][x] != v[sy][sx]:
            ans = min(ans, visited[y][x]-1)
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx<0 or ny<0 or nx>=n or ny>=n:
                continue
            else:
                if (v[ny][nx] == 0 or v[ny][nx] != v[sy][sx]) and visited[ny][nx] == 0:
                    visited[ny][nx] = visited[y][x] + 1
                    q.append((nx,ny))

def bfs(sx,sy):
    global islandNum
    queue = deque()
    queue.append((sx,sy))
    v[sy][sx] = islandNum
    while queue:
        x,y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx<0 or ny<0 or nx>=n or ny>=n:
                continue
            else:
                if board[ny][nx] != 0 and v[ny][nx] == 0:
                    v[ny][nx] = islandNum
                    queue.append((nx,ny))
            
n = int(input())
board = [list(map(int,input().split())) for _ in range(n)]
v = [[0] * n for _ in range(n)]
dx = [0,1,0,-1]
dy = [-1,0,1,0]
islandNum = 1
for i in range(n):
    for j in range(n):
        if board[i][j] == 1 and v[i][j] == 0:
            bfs(j,i)
            islandNum += 1

ans = n*2
for i in range(n):
    for j in range(n):
        visited = [[0] * n for _ in range(n)]
        if v[i][j] != 0 and visited[i][j] == 0:
            build_bridge(j,i)

print(ans)

다른 코드 및 설명

  • 섬 번호만큼 for문을 돌면서 build_bridge 함수 내에서 섬 번호에 해당하는 좌표를 큐에 넣어주고 큐가 빌때까지 다음 좌표 탐색을 실시한다.
from collections import deque

#섬 구분하기
def bfs(sx,sy):
    global islandNum #섬 번호 변수
    queue = deque()
    queue.append((sx,sy))
    v[sy][sx] = islandNum #리스트 v에 섬 번호를 저장한다. 현재 좌표의 섬 번호는 islandNum.
    while queue:
        x,y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx<0 or ny<0 or nx>=n or ny>=n:
                continue
            else:
                #다음 좌표가 육지(1)이고, 아직 방문안했다면
                if board[ny][nx] != 0 and v[ny][nx] == 0:
                    #다음 좌표에 섬 번호 표시한다.
                    v[ny][nx] = islandNum
                    queue.append((nx,ny))

#다리 놓기
def build_bridge(num):
    global ans
    #거리를 저장할 리스트를 생성한다. 초기 좌표값은 -1
    distance = [[-1]*n for _ in range(n)]
    q = deque()
    #섬 번호를 표시한 그리드를 돌면서 섬 번호에 해당하는 좌표를 큐에 넣는다.
    for i in range(n):
        for j in range(n):
            if v[i][j] == num:
                q.append((j,i))
                #거리는 0부터 시작하므로 섬에 해당하는 좌표 값0으로 갱신한다.
                distance[i][j] = 0
    while q:
        x,y = q.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            #범위를 벗어나면 다음으로
            if nx<0 or ny<0 or nx>=n or ny>=n:
                continue
            #다음 좌표의 섬 번호가 0 초과(육지)이고, 현재 섬 번호가 아니라면 
            if v[ny][nx] > 0 and v[ny][nx] != num:
                #현재 좌표의 거리 정보와 ans 중 최소값을 ans에 넣는다.
                ans = min(ans, distance[y][x])
                return #리턴해준다.
            #만약 바다이고, 아직 방문 안했다면, 거리 값을 갱신한다.
            if v[ny][nx] == 0 and distance[ny][nx] == -1:
                distance[ny][nx] = distance[y][x] + 1
                q.append((nx, ny))
            
n = int(input())
board = [list(map(int,input().split())) for _ in range(n)]
v = [[0] * n for _ in range(n)]
dx = [0,1,0,-1]
dy = [-1,0,1,0]

#가로세로 i,j에 해당하는 좌표에 섬 번호를 바꾼다.
islandNum = 1
for i in range(n):
    for j in range(n):
        if board[i][j] == 1 and v[i][j] == 0:
            bfs(j,i)
            islandNum += 1 #bfs한번 실행되고 나면 섬 번호를 1씩 올려준다.

ans = n*2

for i in range(1, islandNum):
    build_bridge(i)

print(ans)

 

'Baekjoon > DFS와 BFS' 카테고리의 다른 글

[백준] 16953 A → B (실버2)  (1) 2023.07.13
🥇[백준] 1941 소문난 칠공주 (골드3) / DFS, BFS, 백트래킹  (0) 2023.05.03
🥇[백준] 1987 알파벳 (골드4) / DFS, list, set, dict 시간복잡도 정리  (0) 2023.05.01
[백준] 1743 음식물 피하기 (실버1) / DFS  (1) 2023.04.30
🥇[백준] 10026 적록색약 (골드5) / BFS  (0) 2023.04.30
'Baekjoon/DFS와 BFS' 카테고리의 다른 글
  • [백준] 16953 A → B (실버2)
  • 🥇[백준] 1941 소문난 칠공주 (골드3) / DFS, BFS, 백트래킹
  • 🥇[백준] 1987 알파벳 (골드4) / DFS, list, set, dict 시간복잡도 정리
  • [백준] 1743 음식물 피하기 (실버1) / DFS
hellosonic
hellosonic
hellosonic
꾸준함
hellosonic
전체
오늘
어제
  • 분류 전체보기 (285)
    • SSAFY (4)
    • 프로그래머스 데브코스 (26)
    • Diary (1)
    • JavaScript (20)
    • ToyPJ (13)
      • Python-Django (13)
    • CS지식 (11)
      • 자료구조 (5)
      • 개발 상식 (2)
      • 네트워크 (4)
    • Baekjoon (141)
      • IM Level (57)
      • DFS와 BFS (21)
      • 백트래킹 (21)
      • DP (3)
      • 이분탐색 (4)
      • 구현 (14)
    • Programmers (13)
      • Lv1 (4)
      • Lv2 (9)
    • SWEA (SW Expert Academy) (52)
      • D1 (5)
      • D2 (7)
      • D3 (40)
    • 이코테 (4)
    • Grammar (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기
  • 관리자

공지사항

인기 글

태그

  • JS
  • 그리디
  • 파이썬 1269
  • 파이썬 1436
  • 프론트엔드 데브코스
  • 프로그래머스 데브코스
  • 자바스크립트 기본기
  • 파이썬
  • SWEA 파이썬
  • 국비지원교육
  • 코딩부트캠프
  • 파이썬 1946
  • 백준 18870
  • SWEA D2
  • 프로그래머스
  • 백준 14891
  • SWEA
  • 파이썬 2529
  • 파이썬 11478
  • SWEA/D3
  • 자바스크립트
  • 이코테
  • 구현
  • 백준
  • 백준 2999
  • javascript ux
  • 백준 5212
  • 백준 1157
  • 리액트 todolist
  • SWEA D3

최근 댓글

최근 글

hELLO · Designed By 정상우.
hellosonic
🥇[백준] 2146 다리 만들기 (골드3) / BFS
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.