Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

125 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

μ½”ν…Œ 곡뢀정리 (Python)

  1. DFS
  2. BFS
  3. DFS vs BFS
  4. Dynamic Programming
  5. 이뢄맀칭
  6. deque
  7. heapq

πŸ“šDFS

βœ”οΈ μ„€λͺ…

DFS(Depth-First Search, 깊이 μš°μ„  탐색)λŠ” κ·Έλž˜ν”„λ‚˜ 트리의 λͺ¨λ“  λ…Έλ“œλ₯Ό 탐색할 λ•Œ μ‚¬μš©ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€. DFSλŠ” ν•œ 경둜둜 μ΅œλŒ€ν•œ 깊이 νƒμƒ‰ν•œ ν›„, 더 이상 갈 곳이 μ—†μœΌλ©΄ 이전 μ •μ μœΌλ‘œ λŒμ•„κ°€ λ‹€λ₯Έ 경둜λ₯Ό νƒμƒ‰ν•˜λŠ” λ°©μ‹μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.

βœ”οΈ νŠΉμ§•

  • μŠ€νƒ(Stack) 자료 ꡬ쑰λ₯Ό 기반으둜 λ™μž‘ν•©λ‹ˆλ‹€. 이λ₯Ό κ΅¬ν˜„ν•  λ•Œ μ‹€μ œ μŠ€νƒμ„ μ‚¬μš©ν•  μˆ˜λ„ μžˆμ§€λ§Œ, μž¬κ·€ 호좜 μ‹œ λ‚΄λΆ€μ μœΌλ‘œ μŠ€νƒμ΄ μ‚¬μš©λ©λ‹ˆλ‹€.
  • κ·Έλž˜ν”„ λ˜λŠ” 트리의 λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜λŠ”λ° μ ν•©ν•©λ‹ˆλ‹€.
  • 깊이λ₯Ό μš°μ„ μ μœΌλ‘œ νƒμƒ‰ν•˜λ―€λ‘œ νŠΉμ • 경둜의 λκΉŒμ§€ λ„λ‹¬ν•œ ν›„, κ·Έ κ²½λ‘œκ°€ μ™„λ£Œλ˜λ©΄ λ‹€μ‹œ λŒμ•„κ°€μ„œ λ‹€λ₯Έ 경둜λ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€.
  • λ°©λ¬Έν•œ λ…Έλ“œλ₯Ό κΈ°μ–΅ν•˜λŠ” λ°©λ¬Έ λ°°μ—΄(visited)을 μ‚¬μš©ν•˜μ—¬ ν•œ 번 λ°©λ¬Έν•œ λ…Έλ“œλ₯Ό λ‹€μ‹œ λ°©λ¬Έν•˜μ§€ μ•Šλ„λ‘ λ°©μ§€ν•©λ‹ˆλ‹€.

βœ”οΈ μž¬κ·€λ°©μ‹ vs μŠ€νƒλ°©μ‹

  1. μž¬κ·€ 방식
    • μž¬κ·€ ν˜ΈμΆœμ„ 톡해 μŠ€νƒμ˜ 역할을 λŒ€μ‹ ν•˜λ©°, 파이썬의 ν•¨μˆ˜ 호좜 μŠ€νƒμ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • β€ΌοΈμ€‘μš”β€ΌοΈ ν•˜μ§€λ§Œ μž¬κ·€ κΉŠμ΄κ°€ κΉŠμ–΄μ§ˆ 경우 μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš°κ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 탐색 κΉŠμ΄κ°€ κΉŠμ–΄μ§€λ©΄ sys.setrecursionlimit()을 μ‚¬μš©ν•˜μ—¬ μž¬κ·€ ν•œλ„λ₯Ό λŠ˜λ¦¬κΈ°λ„ ν•©λ‹ˆλ‹€.
    • μ½”λ“œλŠ” κ°„κ²°ν•˜μ§€λ§Œ, 큰 κ·Έλž˜ν”„λ‚˜ κΉŠμ€ νƒμƒ‰μ—μ„œλŠ” μœ„ν—˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. μŠ€νƒ 방식
    • λͺ…μ‹œμ μΈ μŠ€νƒ 자료 ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš° 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.
    • μž¬κ·€ 호좜 없이도 κ΅¬ν˜„ κ°€λŠ₯ν•˜λ©°, λ©”λͺ¨λ¦¬ 관리에 μžˆμ–΄μ„œ μ’€ 더 효율적일 수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ½”λ“œκ°€ 쑰금 더 λ³΅μž‘ν•΄μ§ˆ 수 μžˆμ§€λ§Œ, μž¬κ·€λ₯Ό ν”Όν•  수 μžˆλŠ” μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

βœ”οΈ ν™œμš© μ˜ˆμ‹œ (μž¬κ·€) 문제: μœ κΈ°λ† λ°°μΆ”

direction = [(0, -1), (0, 1), (-1, 0), (1, 0)] # 쒌우 μƒν•˜
m, n, k = 10, 8, 17 # 농μž₯의 (κ°€λ‘œ, μ„Έλ‘œ, λ°°μΆ” 갯수)

farm = [
    [1, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
    [0, 0, 1, 1, 0, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 1, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
visited = [[False] * m for _ in range(n)]  
answer = 0

def dfs(x, y, farm, visited):
    visited[y][x] = True
    
    for dy, dx in direction:
        nx, ny = dx + x, dy + y
        
        if 0 <= nx < m and 0 <= ny < n:
            if farm[ny][nx] == 1 and not visited[ny][nx]:
                dfs(nx, ny, farm, visited)

for y in range(n):
    for x in range(m):
        if not visited[y][x] and farm[y][x] == 1:
            dfs(x, y, farm, visited)
            answer += 1

print(answer) # 5

βœ”οΈ ν™œμš© μ˜ˆμ‹œ (μŠ€νƒ) 문제: μœ κΈ°λ† λ°°μΆ”

direction = [(0, -1), (0, 1), (-1, 0), (1, 0)] # 쒌우 μƒν•˜
m, n, k = 10, 8, 17 # 농μž₯의 (κ°€λ‘œ, μ„Έλ‘œ, λ°°μΆ” 갯수)

farm = [
    [1, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
    [0, 0, 1, 1, 0, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 1, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 1], 
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
visited = [[False] * m for _ in range(n)]  
answer = 0

def dfs(x, y): 
    stack = [(x, y)]
    visited[y][x] = True

    while stack:
        cx, cy = stack.pop()
        for dy, dx in direction:
            nx, ny = dx + cx, dy + cy
            if 0 <= nx < m and 0 <= ny < n:
                if not visited[ny][nx] and farm[ny][nx] == 1:
                    visited[ny][nx] = True
                    stack.append((nx, ny))

for y in range(n):
    for x in range(m):
        if not visited[y][x] and farm[y][x] == 1:
            dfs(x, y)
            answer += 1

print(answer) # 5

πŸ“šBFS

βœ”οΈ μ„€λͺ…

BFS(Breadth-First Search)λŠ” κ·Έλž˜ν”„ λ˜λŠ” νŠΈλ¦¬μ—μ„œμ˜ 탐색 μ•Œκ³ λ¦¬μ¦˜ 쀑 ν•˜λ‚˜λ‘œ, λ„ˆλΉ„ μš°μ„  탐색 방법을 μ‚¬μš©ν•©λ‹ˆλ‹€. BFSλŠ” λ¨Όμ € μ‹œμž‘ λ…Έλ“œμ—μ„œ κ°€κΉŒμš΄ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œ ν›„ 점차 멀리 μžˆλŠ” λ…Έλ“œλ‘œ μ΄λ™ν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ 큐(Queue)λ₯Ό μ‚¬μš©ν•˜μ—¬ ν˜„μž¬ 탐색 쀑인 λ…Έλ“œμ˜ 이웃을 μ°¨λ‘€λŒ€λ‘œ μ €μž₯ν•˜κ³  νƒμƒ‰ν•©λ‹ˆλ‹€.

βœ”οΈ νŠΉμ§•

  • μ΅œλ‹¨ 경둜 탐색: BFSλŠ” κ°€μ€‘μΉ˜κ°€ μ—†λŠ” κ·Έλž˜ν”„μ—μ„œ 두 λ…Έλ“œ κ°„μ˜ μ΅œλ‹¨ 경둜λ₯Ό 보μž₯ν•©λ‹ˆλ‹€.
  • FIFO 큐 μ‚¬μš©: λ°©λ¬Έν•  λ…Έλ“œλ₯Ό 큐에 μ €μž₯ν•˜κ³ , λ¨Όμ € λ“€μ–΄μ˜¨ λ…Έλ“œλ₯Ό λ¨Όμ € νƒμƒ‰ν•©λ‹ˆλ‹€.

βœ”οΈ λ™μž‘μˆœμ„œ

  1. μ‹œμž‘ λ…Έλ“œλ₯Ό 큐에 μ‚½μž…ν•©λ‹ˆλ‹€.
  2. νμ—μ„œ λ…Έλ“œλ₯Ό ν•˜λ‚˜ κΊΌλ‚΄κ³  ν•΄λ‹Ή λ…Έλ“œλ₯Ό λ°©λ¬Έν•©λ‹ˆλ‹€.
  3. λ°©λ¬Έν•œ λ…Έλ“œμ— μ—°κ²°λœ 인접 λ…Έλ“œλ₯Ό λͺ¨λ‘ 큐에 μ‚½μž…ν•©λ‹ˆλ‹€.
  4. 큐가 빌 λ•ŒκΉŒμ§€ 이 과정을 λ°˜λ³΅ν•©λ‹ˆλ‹€.

βœ”οΈ ν™œμš© μ˜ˆμ‹œ 문제: μˆ¨λ°”κΌ­μ§ˆ

from collections import deque

 # ν˜„μž¬ μœ„μΉ˜, λͺ©ν‘œ 도달 μœ„μΉ˜
N, K = 5, 17
visited = [False] * 100001  
visited[N] = True  

def bfs():
    q = deque([(N, 0)])
    while q:
        n, sec = q.popleft()
        if n == K:
            # λͺ©ν‘œ λ„λ‹¬μ‹œ 좜λ ₯ ν›„ μ’…λ£Œ
            print(sec) 
            break
        # ν˜„μž¬ μœ„μΉ˜μ—μ„œ (-1, +1, *2) 3κ°€μ§€ κ°€λŠ₯성이 μžˆλŠ” μΌ€μ΄μŠ€λ₯Ό κ³„μ‚°ν•œλ‹€.
        for next in (n - 1, n + 1, n * 2):
            # λ°©λ¬Έμ²˜λ¦¬μ™€ 재방문 λ°©μ§€
            if 0 <= next <= 100000 and not visited[next]:
                visited[next] = True  
                q.append((next, sec + 1)) 

bfs()

πŸ“šDFS vs BFS

βœ”οΈ 탐색 λ°©μ‹μ˜ 차이

DFSλŠ” ν•˜λ‚˜μ˜ 경둜λ₯Ό λκΉŒμ§€ νƒμƒ‰ν•œ ν›„ λ‹€μ‹œ λŒμ•„μ™€μ„œ λ‹€λ₯Έ 경둜λ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€. 즉, 깊이 μš°μ„ μœΌλ‘œ 탐색을 μ§„ν–‰ν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ μŠ€νƒ(Stack) 자료 κ΅¬μ‘°λ‚˜ μž¬κ·€ ν•¨μˆ˜ ν˜ΈμΆœμ„ μ‚¬μš©ν•©λ‹ˆλ‹€. λ¨Όμ € 깊이(depth)λ₯Ό μš°μ„ μœΌλ‘œ νƒμƒ‰ν•˜λ―€λ‘œ, ν•œ λ…Έλ“œμ—μ„œ 갈 수 μžˆλŠ” 경둜λ₯Ό λͺ¨λ‘ νƒμƒ‰ν•œ 뒀에야 λ‹€λ₯Έ 경둜둜 λŒμ•„μ˜΅λ‹ˆλ‹€.

BFSλŠ” λ¨Όμ € μ‹œμž‘ λ…Έλ“œμ—μ„œ κ°€κΉŒμš΄ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜κ³ , κ·Έ λ‹€μŒμœΌλ‘œ 멀리 μžˆλŠ” λ…Έλ“œλ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€. 즉, λ„ˆλΉ„ μš°μ„ μœΌλ‘œ 탐색을 μ§„ν–‰ν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ 큐(Queue) 자료 ꡬ쑰λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. λ¨Όμ € λ™μΌν•œ 레벨(level)의 λͺ¨λ“  λ…Έλ“œλ₯Ό νƒμƒ‰ν•œ ν›„, λ‹€μŒ 레벨둜 μ΄λ™ν•©λ‹ˆλ‹€.

βœ”οΈ 자료 ꡬ쑰

DFSλŠ” 주둜 μŠ€νƒ(μž¬κ·€ 호좜 μ‹œ μ‹œμŠ€ν…œ μŠ€νƒ)을 μ‚¬μš©ν•˜μ—¬ κ°€μž₯ μ΅œκ·Όμ— λ°©λ¬Έν•œ λ…Έλ“œλ₯Ό κΈ°μ€€μœΌλ‘œ λ‹€μŒ 탐색을 μ§„ν–‰ν•©λ‹ˆλ‹€.
BFSλŠ” 주둜 큐λ₯Ό μ‚¬μš©ν•˜μ—¬ λ¨Όμ € λ“€μ–΄μ˜¨ λ…Έλ“œλΆ€ν„° μ°¨λ‘€λ‘œ νƒμƒ‰ν•©λ‹ˆλ‹€.

βœ”οΈ μ‚¬μš© μ˜ˆμ‹œ

  1. DFS μ‚¬μš© μ˜ˆμ‹œ

    • 경둜 탐색: νŠΉμ • λ…Έλ“œμ—μ„œ νŠΉμ • λ…Έλ“œλ‘œ κ°€λŠ” 경둜λ₯Ό μ°Ύκ±°λ‚˜, 미둜 탐색 λ“±μ˜ λ¬Έμ œμ— μ ν•©ν•©λ‹ˆλ‹€.
    • λ°±νŠΈλž˜ν‚Ή: κ°€λŠ₯ν•œ λͺ¨λ“  경우λ₯Ό μ‹œλ„ν•΄μ•Ό ν•  λ•Œ μ‚¬μš©λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 퍼즐 문제, μ‘°ν•©/μˆœμ—΄ 문제 λ“±μ—μ„œ DFSκ°€ μœ μš©ν•©λ‹ˆλ‹€.
    • 사이클 탐지: DFSλŠ” κ·Έλž˜ν”„μ—μ„œ 사이클이 μ‘΄μž¬ν•˜λŠ”μ§€λ₯Ό ν™•μΈν•˜λŠ” 데 μ ν•©ν•©λ‹ˆλ‹€.
  2. BFS μ‚¬μš© μ˜ˆμ‹œ

    • μ΅œλ‹¨ 경둜 탐색: κ°€μ€‘μΉ˜κ°€ μ—†λŠ” κ·Έλž˜ν”„μ—μ„œ 두 λ…Έλ“œ κ°„μ˜ μ΅œλ‹¨ 경둜λ₯Ό μ°ΎλŠ” 데 μ ν•©ν•©λ‹ˆλ‹€.
    • 계측 탐색: ν•œ λ ˆλ²¨μ”© 순차적으둜 탐색해야 ν•˜λŠ” λ¬Έμ œμ— μœ μš©ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ†Œμ…œ λ„€νŠΈμ›Œν¬μ—μ„œ 친ꡬ 관계λ₯Ό 탐색할 λ•Œ 같은 레벨의 μ‚¬λžŒλ“€λΆ€ν„° μ°¨λ‘€λ‘œ νƒμƒ‰ν•˜λŠ” 것이 μœ λ¦¬ν•©λ‹ˆλ‹€.
    • 레벨 탐색: 트리의 각 λ ˆλ²¨μ—μ„œ λ…Έλ“œλ₯Ό 순차적으둜 νƒμƒ‰ν•˜λŠ” 경우 BFSκ°€ μ ν•©ν•©λ‹ˆλ‹€.

πŸ“š Dynamic Programming

βœ”οΈ μ„€λͺ…

동적 ν”„λ‘œκ·Έλž˜λ°μ€ λ³΅μž‘ν•œ 문제λ₯Ό 더 κ°„λ‹¨ν•œ ν•˜μœ„ 문제둜 λ‚˜λˆ„μ–΄ ν•΄κ²°ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜ 섀계 κΈ°λ²•μž…λ‹ˆλ‹€. 이 기법은 μ΅œμ ν™” 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λ©°, μ£Όμ–΄μ§„ 문제λ₯Ό 잘 μ •μ˜λœ ν•˜μœ„ 문제둜 λ‚˜λˆ„κ³ , 이 ν•˜μœ„ 문제의 κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ—¬ 쀑볡 계산을 ν”Όν•˜λŠ” λ°©μ‹μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€. DPλŠ” 주둜 μ΅œμ ν™” 문제, 경둜 탐색 문제 및 μ‘°ν•© λ¬Έμ œμ— μ μš©λ©λ‹ˆλ‹€.

βœ”οΈ νŠΉμ§•

  • 졜적 λΆ€λΆ„ ꡬ쑰: 문제의 졜적 해결책이 ν•˜μœ„ 문제의 졜적 ν•΄κ²°μ±…μœΌλ‘œ ꡬ성될 수 μžˆμŠ΅λ‹ˆλ‹€. 즉, 큰 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μž‘μ€ 문제λ₯Ό ν•΄κ²°ν•˜κ³  κ·Έ κ²°κ³Όλ₯Ό κ²°ν•©ν•˜μ—¬ 졜적 ν•΄λ₯Ό λ„μΆœν•©λ‹ˆλ‹€.
  • 쀑볡 ν•˜μœ„ 문제: λ™μΌν•œ ν•˜μœ„ λ¬Έμ œκ°€ μ—¬λŸ¬ 번 λ°œμƒν•©λ‹ˆλ‹€. 이λ₯Ό λ©”λͺ¨μ΄μ œμ΄μ…˜ λ˜λŠ” ν…Œμ΄λΈ”μ„ μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν•¨μœΌλ‘œμ¨ νš¨μœ¨μ„±μ„ λ†’μž…λ‹ˆλ‹€.
  • λ©”λͺ¨μ΄μ œμ΄μ…˜: κ³„μ‚°ν•œ κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ—¬ λ™μΌν•œ 계산을 λ°˜λ³΅ν•˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€. μž¬κ·€μ  방법과 ν•¨κ»˜ μ‚¬μš©λ˜λŠ” κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€.
  • νƒ‘λ‹€μš΄ λ˜λŠ” λ°”ν…€μ—… μ ‘κ·Ό: DPλŠ” ν•˜μœ„ 문제λ₯Ό ν•΄κ²°ν•˜λŠ” μˆœμ„œμ— 따라 두 κ°€μ§€ μ ‘κ·Ό λ°©μ‹μœΌλ‘œ λ‚˜λ‰©λ‹ˆλ‹€.
  • νƒ‘λ‹€μš΄: μž¬κ·€μ μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•˜κ³ , 이미 κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ—¬ ν•„μš”ν•  λ•Œ μž¬μ‚¬μš©ν•©λ‹ˆλ‹€.
  • λ°”ν…€μ—…: κ°€μž₯ μž‘μ€ ν•˜μœ„ λ¬Έμ œλΆ€ν„° μ°¨κ·Όμ°¨κ·Ό ν•΄κ²°ν•΄ λ‚˜κ°€λ©΄μ„œ 큰 문제의 해결책을 λ§Œλ“€μ–΄ λ‚˜κ°‘λ‹ˆλ‹€.

βœ”οΈ μ˜ˆμ‹œ

  • ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄: n번째 항을 κ³„μ‚°ν•˜λŠ” 문제λ₯Ό DP둜 ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 각 항은 이전 두 ν•­μ˜ ν•©μœΌλ‘œ μ •μ˜λ˜λ©°, 쀑볡 계산을 ν”Όν•˜κΈ° μœ„ν•΄ 이미 κ³„μ‚°λœ 값을 μ €μž₯ν•©λ‹ˆλ‹€.
  • 0-1 λ°°λ‚­ 문제: μ£Όμ–΄μ§„ λ¬Όκ±΄λ“€μ˜ κ°€μΉ˜μ™€ 무게λ₯Ό 기반으둜 μ΅œλŒ€ κ°€μΉ˜λ₯Ό μ–»κΈ° μœ„ν•΄ μ œν•œλœ μš©λŸ‰μ˜ 배낭에 μ–΄λ–€ 물건을 λ‹΄μ•„μ•Ό ν•˜λŠ”μ§€λ₯Ό κ²°μ •ν•˜λŠ” λ¬Έμ œμž…λ‹ˆλ‹€. DPλ₯Ό μ‚¬μš©ν•˜μ—¬ 각 물건을 ν¬ν•¨ν•˜κ±°λ‚˜ ν¬ν•¨ν•˜μ§€ μ•Šμ„ 경우의 μ΅œλŒ€ κ°€μΉ˜λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.
  • RGB 거리 문제: 이 λ¬Έμ œλŠ” N개의 집을 λΉ¨κ°•, 초둝, νŒŒλž‘μœΌλ‘œ 색칠할 λ•Œμ˜ μ΅œμ†Œ λΉ„μš©μ„ κ³„μ‚°ν•©λ‹ˆλ‹€. 각 집은 μΈμ ‘ν•œ μ§‘κ³Ό 같은 μƒ‰μœΌλ‘œ μΉ ν•  수 μ—†λŠ” μ œμ•½μ΄ 있으며, DPλ₯Ό 톡해 각 μ§‘μ˜ 색칠 λΉ„μš©μ„ μ΅œμ†Œν™”ν•©λ‹ˆλ‹€.

πŸ“šμ΄λΆ„λ§€μΉ­

βœ”οΈ μ„€λͺ…

이뢄 κ·Έλž˜ν”„μ—μ„œ 두 개의 λ…λ¦½λœ μ§‘ν•© μ‚¬μ΄μ—μ„œ κ°€λŠ₯ν•œ μ΅œλŒ€ 맀칭을 μ°ΎλŠ” λ¬Έμ œμž…λ‹ˆλ‹€. 이뢄 κ·Έλž˜ν”„λŠ” 두 개의 μ§‘ν•©μœΌλ‘œ 정점듀이 λ‚˜λ‰˜μ–΄ 있으며, 각 간선은 μ„œλ‘œ λ‹€λ₯Έ μ§‘ν•©μ˜ 정점 μ‚¬μ΄μ—μ„œλ§Œ μ—°κ²°λ©λ‹ˆλ‹€.

βœ”οΈ νŠΉμ§•

  • λ§€μΉ­(Matching): 이뢄 λ§€μΉ­μ—μ„œ "λ§€μΉ­"은 κ°„μ„ μ˜ λΆ€λΆ„μ§‘ν•©μœΌλ‘œ, 각 정점이 μ΅œλŒ€ ν•˜λ‚˜μ˜ κ°„μ„ μ—λ§Œ ν¬ν•¨λ˜λ„λ‘ μ„ νƒλ©λ‹ˆλ‹€. 즉, 각 정점이 ν•œ 번만 맀칭에 μ°Έμ—¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ΅œλŒ€ λ§€μΉ­(Maximum Matching): κ°€λŠ₯ν•œ ν•œ μ΅œλŒ€ν•œ λ§Žμ€ 간선을 μ„ νƒν•˜μ—¬ 맀칭을 κ΅¬μ„±ν•˜λŠ” 것을 λ§ν•©λ‹ˆλ‹€. μ΅œλŒ€ 맀칭을 κ΅¬ν•˜λŠ” 것이 이뢄 λ§€μΉ­ 문제의 ν•΅μ‹¬μž…λ‹ˆλ‹€.
  • DFS와 BFS의 ν™œμš©: 이뢄 맀칭을 ν•΄κ²°ν•˜λŠ” 일반적인 방식은 깊이 μš°μ„  탐색(DFS)을 μ‚¬μš©ν•΄ κ΅ν™˜ 경둜λ₯Ό νƒμƒ‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. κ²½μš°μ— 따라 BFS(λ„ˆλΉ„ μš°μ„  탐색)도 보쑰적으둜 μ‚¬μš©λ©λ‹ˆλ‹€.

βœ”οΈ μ˜ˆμ‹œ

  • ꡬ인/ꡬ직 λ§€μΉ­: 두 μ§‘ν•© 쀑 ν•˜λ‚˜λ₯Ό ꡬ직자, λ‹€λ₯Έ ν•˜λ‚˜λ₯Ό 일자리둜 μ„€μ •ν•˜μ—¬ 각각의 κ΅¬μ§μžμ™€ μΌμžλ¦¬κ°€ μ—°κ²°λœ 경우, κ°€λŠ₯ν•œ 졜적의 맀칭을 찾을 수 μžˆμŠ΅λ‹ˆλ‹€.
  • μž‘μ—… ν• λ‹Ή 문제: μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλŠ” κΈ°κ³„λ‚˜ μ‚¬λžŒκ³Ό 각 μž‘μ—… κ°„μ˜ 졜적 할당을 μ°ΎλŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€.
  • λŒ€ν•™ μž…μ‹œ, νŒŒν‹° ꡬ성: 학생-전곡 λ§€μΉ­, νŒŒν‹°λ‚˜ 그룹을 κ΅¬μ„±ν•˜λŠ” λ“±μ˜ λ¬Έμ œμ—λ„ 이뢄 λ§€μΉ­ μ•Œκ³ λ¦¬μ¦˜μ΄ μ‚¬μš©λ©λ‹ˆλ‹€.

βœ”οΈ μ˜ˆμ‹œ μ—΄ν˜ˆκ°•ν˜Έ

import sys

sys.setrecursionlimit(100000)

# μž‘μ—…μž, μž‘μ—…
N, M = map(int, input().split()) 

tasks = {}
assigned = [None] * (M + 1) # λ§€μΉ­ μƒνƒœλ₯Ό 기둝

for i in range(1, N + 1):
    line = list(map(int, input().split()))
    tasks[i] = line[1:]

# 맀칭을 μˆ˜ν–‰
def assign(staff, visited): 
    for task in tasks[staff]:
        if visited[task]:  
            continue
        visited[task] = True
        # μž‘μ—…μžκ°€ ν• λ‹Ήλ˜μ–΄ μžˆμ§€ μ•Šκ±°λ‚˜ 이미 ν• λ‹Ήλ˜μ–΄μžˆλ‹€λ©΄ ν•΄λ‹Ή μž‘μ—…μžκ°€ λ‹€λ₯Έ μž‘μ—…μœΌλ‘œ 양보할 수 μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.
        if assigned[task] is None or assign(assigned[task], visited): 
            assigned[task] = staff 
            return True
    return False

for i in range(1, N + 1):
    # μž‘μ—…μžλ₯Ό μˆœν™”ν• λ•Œ λ§ˆλ‹€ μž‘μ—… visitedλ₯Ό μ΄ˆκΈ°ν™”ν•œλ‹€.
    visited = [False] * (M + 1) 
    assign(i, visited)

print(sum(1 for a in assigned if a != None))

πŸ“šdeque

βœ”οΈ μ„€λͺ…

dequeλŠ” Python의 collections λͺ¨λ“ˆμ—μ„œ μ œκ³΅ν•˜λŠ” μ–‘λ°©ν–₯ 큐둜, λ¦¬μŠ€νŠΈμ™€ μœ μ‚¬ν•˜μ§€λ§Œ μ–‘μͺ½ λμ—μ„œ λΉ λ₯΄κ³  효율적으둜 μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ μ œκ±°ν•  수 μžˆλŠ” 자료 κ΅¬μ‘°μž…λ‹ˆλ‹€. dequeλŠ” Double-Ended Queue의 μ•½μžλ‘œ, 큐의 μ–‘μͺ½ λμ—μ„œ μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ μ œκ±°ν•˜λŠ” μž‘μ—…μ„ O(1) μ‹œκ°„ μ•ˆμ— μˆ˜ν–‰ν•  수 μžˆμ–΄, λ¦¬μŠ€νŠΈλ³΄λ‹€ νš¨μœ¨μ μž…λ‹ˆλ‹€.

βœ”οΈ νŠΉμ§•

  • μ–‘λ°©ν–₯으둜 μ‚½μž…κ³Ό μ‚­μ œκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • μ•žμͺ½μ—μ„œ μΆ”κ°€/μ‚­μ œ, λ’€μͺ½μ—μ„œ μΆ”κ°€/μ‚­μ œ λͺ¨λ‘ μ§€μ›ν•©λ‹ˆλ‹€.
  • λ¦¬μŠ€νŠΈλŠ” μ–‘μͺ½ λμ—μ„œ μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ μ‚­μ œν•˜λŠ” 데 O(n) μ‹œκ°„μ΄ 걸릴 수 μžˆμ§€λ§Œ, dequeλŠ” O(1)의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό 보μž₯ν•©λ‹ˆλ‹€.
  • 큐, μŠ€νƒ, 덱 λ“± λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ ν™œμš© κ°€λŠ₯ν•©λ‹ˆλ‹€.

βœ”οΈ 간단 μ‚¬μš©λ°©λ²•

from collections import deque

l = [1,2,3,4]

dq = deque(l) # deque([1, 2, 3, 4])
dq.append(5) # deque([1, 2, 3, 4, 5])
dq.appendleft(6) # deque([6, 1, 2, 3, 4, 5])
first = dq.popleft() # 6
last = dq.pop() # 5
print(dq) # deque([1, 2, 3, 4])

πŸ“šheapq

βœ”οΈ μ„€λͺ…

heapqλŠ” Pythonμ—μ„œ νž™ 큐(μš°μ„ μˆœμœ„ 큐)λ₯Ό 효율적으둜 μ‚¬μš©ν•  수 μžˆλ„λ‘ μ§€μ›ν•˜λŠ” λͺ¨λ“ˆμž…λ‹ˆλ‹€. νž™μ€ 이진 트리 기반의 자료 ꡬ쑰둜, μ΅œμ†Œκ°’μ΄λ‚˜ μ΅œλŒ€κ°’μ„ λΉ λ₯΄κ²Œ μ°Ύμ•„λ‚΄κΈ° μœ„ν•œ μš°μ„ μˆœμœ„ 큐λ₯Ό κ΅¬ν˜„ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€. heapq λͺ¨λ“ˆμ€ 기본적으둜 μ΅œμ†Œ νž™(min-heap)을 μ œκ³΅ν•©λ‹ˆλ‹€.

βœ”οΈ μ˜ˆμ‹œ

import heapq

ints = [40, 50, 20]

heapq.heapify(ints) # [20, 50, 40]
min = heapq.heappop(ints) # 20
heapq.heappush(ints, 100) # [40, 50, 100]

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages