
graph[i]는, 시작 노드 i와 연결된 모든 노드의 리스트# 아래 그림의 그래프를 인접 리스트로 나타냄
# graph[i]: 시작 노드 `i`와 연결된 모든 노드의 리스트
graph = [
[], # 0번노드는 사용 안 함
[2, 3, 8],
[1, 7],
[1, 4, 5],
[3, 5],
[3, 4],
[7],
[2, 6, 8],
[1, 7]
]

dfs(x)를 시작 노드부터 호출x를 방문하고, 인접 노드 i를 순회i가 있으면 dfs(i) 재귀 호출# 재귀?? 이거 필수!!
import sys
sys.setrecursionlimit(10 ** 9)
# visited[i]: i번 노드의 방문 여부
visited = [False] * len(graph)
def dfs(x):
# (1) 노드 x를 방문 처리
visited[x] = True
print(x, end=" ")
# (2) 미방문한 인접 노드 i를 재귀적으로 호출
for i in graph[x]: # 노드 x의 인접 노드 i
if not visited[i]: # 미방문한 경우
dfs(i, graph, visited) # 재귀호출
dfs(1) # 1번 노드부터 DFS 탐색 시작
# 1 2 7 6 8 3 4 5
collections.deque)를 활용
from collections import deque
# distance[i]: 시작 노드와 i번 노드 간 최단거리
# 방문하지 않아 거리를 계산하지 못한 노드는 None
distance = [None] * 9
def bfs(start):
# (1) 시작 노드를 큐에 삽입, 거리는 0으로 처리
queue = deque([start])
distance[start] = 0
while queue:
# (2a) 큐에서 노드를 꺼냄
x = queue.popleft()
print(x, end=" ")
# (2b) 방문하지 않은 인접 노드를 모두 큐에 삽입
for i in graph[x]:
if distance[i] is None:
queue.append(i)
# (2c) 거리: 현재 노드까지의 거리 + 1
distance[i] = distance[x] + 1
# 시작 노드는 1번 노드
bfs(1) # 1 2 3 8 7 4 5 6
# 시작 노드와 각 노드의 거리
print(*distance[1:]) # 0 1 1 2 2 3 2 1

import heapq
INF = float('inf')
# graph[i]: 시작 노드 `i`와 연결된 간선의 리스트
# (도착 노드, 비용 순)
graph = [
[],
[(2, 2), (4, 1)],
[(3, 3), (4, 2)],
[(2, 3), (6, 5)],
[(3, 3), (5, 1)],
[(3, 1), (6, 2)],
[]
]
# dist_table[i]: 시작 노드와 각 노드 간 최단 거리
dist_table = [INF] * len(graph)
(최단거리, 노드 번호) 순으로 삽입queue = []
# 시작 노드를 큐에 삽입 및 거리 0으로 설정
heapq.heappush(queue, (0, 1)) # (최단거리, 노드번호)
dist_table[1] = 0
(최단거리, 노드번호)를 우선순위 큐에 넣기while queue:
# 가장 최단 거리가 짧은 노드 i 꺼내기
i_dist, i = heapq.heappop(queue)
# 이미 더 짧은 거리로 방문한 경우 무시
if i_dist > dist_table[i]:
continue
# i의 인접 노드 j 확인
for j, j_dist in graph[i]:
# j: 인접 노드, j_dist: 간선 가중치
# 현재 노드를 거쳐, 인접 노드로 이동하는 거리
new_dist = i_dist + j_dist
# 거리가 더 짧으면 갱신
if new_dist < dist_table[j]:
dist_table[j] = new_dist
heapq.heappush(queue, (new_dist, j))
print(*dist_table[1:]) # 0 2 3 1 2 4
# 현재 격좌 위치를 x, y로
# 격좌의 행의 수를 N, 열의 수를 M으로 둘 때
dx = [-1, 0, 1, 0] # 상, 하, 좌, 우
dy = [0, -1, 0, 1]
for i in range(4):
nx, ny = x + dx[i], y + dy[i] # 상하좌우 인접칸 확인
if 0 <= nx < N and 0 <= ny < M:
# 이후 여기에 dfs 재귀 호출이나, bfs 큐 삽입 등을 수행해야 함

x행 y열일 때, 인접 위치 nx행 ny열을 확인for i in range(4)를 순회하며, nx = x + dx[i], ny = y + dy[i]로 계산i의 값 | nx행 | ny열 | 위치 |
|---|---|---|---|
i == 0 | x-1 | y | 상단 칸 |
i == 1 | x | y-1 | 좌측 칸 |
i == 2 | x+1 | y | 하단 칸 |
i == 3 | x | y+1 | 우측 칸 |
0 <= nx < N and 0 <= ny < M 과 같이




찾는 값 < 노드 값이면 왼쪽 자식을, 찾는 값 > 노드 값이면 오른쪽 자식을 따라감
예시: 피보나치 수열
# memo[i]는 피보나치수열의 i번째 값 (단 i는 1부터 시작)
# 아직 계산하지 못한 경우 None
memo = [None] * 100
# memo[i]는 피보나치수열의 i번째 값
for i in range(1, 100):
# 첫번째, 두번째 값은 1
if i == 1 or i == 2:
memo[i] = 1
# 이후 값은 점화식으로 계산
else:
memo[i] = memo[i - 1] + memo[i - 2]
print(memo[99]) # 218922995834555169026
memo[6] = memo[5] + memo[4], memo[5] = memo[4] + memo[3]이므로, memo[4]가 중복 등장for문을 통해 memo[i]의 값을 계산하면서 저장memo[1], memo[2]는 1)부터 시작memo[i] = memo[i - 1] + memo[i - 2]을 이용해, 순차적으로 저장된 값을 이후 계산에 활용
저는 동적 계획법을 정말 어려워하는 편입니다.
도움이 될 진 모르겠지만 뭐 유념해야 할 점을 정리해 봅니다.
memo[i]에 피보나치 수열의 i번째 수로 정의한다.N번째 수를 찾고 싶으면, memo[N]을 구하면 된다.i가 증가하면 값이 달라진다.memo[1] = 1, memo[2] = 1인 건 확실히 알 수 있다. 얘넬 먼저 채우고 시작한다.memo[i] = memo[i - 1] + memo[i - 2]임을 떠올리는 사람은 없을 거다. 직접 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5... 이렇게 계산을 하며 떠올렸겠지.