Skip to content

Latest commit

Β 

History

History
268 lines (178 loc) Β· 6.06 KB

File metadata and controls

268 lines (178 loc) Β· 6.06 KB

sw-algorithm

DFS(Depth First Search)

μ‚¬μš©λ˜λŠ” 문제 μœ ν˜•

  • λͺ¨λ“  정점을 λ°©λ¬Έν•˜λŠ” 경우
  • 각각의 κ²½λ‘œλ§ˆλ‹€ νŠΉμ§•μ„ μ €μž₯ν•΄μ•Όν•˜λŠ” 경우

κ΅¬ν˜„ 방법

  • μŠ€νƒ

def dfs(v):
    stack = [v]
    visited[v] = True
    print(v)
    while stack:

        for w in graph[v]:
            if not visited[w]:
                print(w)                # λ°©λ¬Έν•œ λ…Έλ“œλ₯Ό 좜λ ₯
                stack.append(v)
                v = w
                visited[v] = True
                break
        else:
            v = stack.pop()             # λ°©λ¬Έν•  수 μžˆλŠ” λ…Έλ“œκ°€ μ—†λ‹€λ©΄ λ°±νŠΈλž˜ν‚Ή


N, M = map(int, input().split())        # 정점, κ°„μ„ 

graph = [[] for _ in range(N + 1)]      # μ •μ μ˜ 수 만큼 생성


for _ in range(M):                      # κ°„μ„  수 만큼 μ§„ν–‰
    x, y = map(int, input().split())
    graph[x].append(y)
    graph[y].append(x)


visited = [False] * (N + 1)
dfs(1)
  • μž¬κ·€
def dfs(v):
    visited[v] = True
    print(v)
    for w in graph[v]:
        if not visited[w]:
            dfs(w)


N, M = map(int, input().split())        # 정점, κ°„μ„ 

graph = [[] for _ in range(N + 1)]          # μ •μ μ˜ 수 만큼 생성


for _ in range(M):                      # κ°„μ„  수 만큼 μ§„ν–‰
    x, y = map(int, input().split())
    graph[x].append(y)
    graph[y].append(x)

visited = [False] * (N + 1)

dfs(1)

dijkstra

μ‚¬μš©λ˜λŠ” 문제 μœ ν˜•

  • νŠΉμ • λ…Έλ“œμ—μ„œ μΆœλ°œν•˜μ—¬ 각각의 λ…Έλ“œμ— μ΅œλ‹¨κ²½λ‘œλ₯Ό κ΅¬ν•˜λŠ” 경우
  • μ–‘μˆ˜μ— ν•΄λ‹Ήν•˜λŠ” κ°€μ€‘μΉ˜λ§Œ ν¬ν•¨ν•˜λŠ” 경우
  • λ„€λΉ„κ²Œμ΄μ…˜ 문제

κ΅¬ν˜„ 방법

  • λ‹¨μˆœ κ΅¬ν˜„ν•˜λŠ” 방법
  1. μ΅œλ‹¨ 거리의 λ…Έλ“œλ₯Ό κ³„μ‚°ν•œλ‹€. => get_samllest()
  2. ν•΄λ‹Ή λ…Έλ“œμ—μ„œ κ°„μ„ μ˜ 거리λ₯Ό κ³„μ‚°ν•˜μ—¬ μž‘μ€ κ°’μœΌλ‘œ updateλ₯Ό ν•΄μ€€λ‹€.
  3. μœ„ 1-2 방법을 λ…Έλ“œμ˜ 수 - 1 만큼 λ°˜λ³΅ν•œλ‹€. => λ…Έλ“œμ˜ 수 - 1μ—μ„œ -1은 μ‹œμž‘ 값을 이미 λ°©λ¬Έ ν–ˆκΈ° λ•Œλ¬Έ
test_case = 0
INF = int(1e9)


def get_smallest():
    minV = INF
    x = y = 0
    for i in range(N):
        for j in range(N):
            if not visited[i][j] and minV > distance[i][j]:
                minV = distance[i][j]
                x = i
                y = j

    return x, y


def dijkstra(x, y):
    distance[x][y+1] = distance[x][y] + cave[x][y+1]
    distance[x+1][y] = distance[x][y] + cave[x+1][y]

    for _ in range(N * N - 1):
        node = get_smallest()

        visited[node[0]][node[1]] = True

        for d_x, d_y in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            n_x = node[0] + d_x
            n_y = node[1] + d_y

            if 0 <= n_x < N and 0 <= n_y < N and not visited[n_x][n_y]:
                new_dist = distance[node[0]][node[1]] + cave[n_x][n_y]
                
                if distance[n_x][n_y] > new_dist :
                    distance[n_x][n_y] = new_dist

    return distance[-1][-1]


while True:
    test_case += 1

    N = int(input())

    if N == 0:
        break

    cave = [list(map(int, input().split())) for _ in range(N)]

    distance = [[INF] * N for _ in range(N)]

    visited = [[False] * N for _ in range(N)]

    visited[0][0] = True
    distance[0][0] = cave[0][0]

    print(f"Problem {test_case}: {dijkstra(0, 0)}")



  • heapqλ₯Ό μ΄μš©ν•˜λŠ” 방법
  1. heapq에 거리에 ν•΄λ‹Ήν•˜λŠ” 값을 push ν•˜μ—¬ μ΅œμ†Œνž™μœΌλ‘œ μ €μž₯ν•œλ‹€.
  2. μ΅œμ†Œ 값에 ν•΄λ‹Ήν•˜λŠ” 값을 pop ν•œλ‹€.
  3. μ΅œμ†Œ 값에 ν•΄λ‹Ήν•˜λŠ” node의 간선을 κ³„μ‚°ν•˜μ—¬ updateν•˜μ—¬ heapq에 push ν•œλ‹€.
  4. μœ„ 1-3방법을 λ°©λ¬Έν•  λ…Έλ“œκ°€ μ—†μ–΄μ§ˆλ•ŒκΉŒμ§€ λ°˜λ³΅ν•œλ‹€.
import heapq

test_case = 0
INF = int(1e9)

def dijkstra(x, y):
    q = []

    distance[x][y+1] = distance[x][y] + cave[x][y+1]
    distance[x+1][y] = distance[x][y] + cave[x+1][y]

    heapq.heappush(q, (distance[x][y+1], x, y+1))
    heapq.heappush(q, (distance[x+1][y], x+1, y))

    while q:
        dist, i, j = heapq.heappop(q)

        visited[i][j] = True

        for d_x, d_y in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            n_x = i + d_x
            n_y = j + d_y

            if 0 <= n_x < N and 0 <= n_y < N and not visited[n_x][n_y]:
                new_dist = dist + cave[n_x][n_y]

                if distance[n_x][n_y] > new_dist:
                    distance[n_x][n_y] = new_dist
                    heapq.heappush(q, (new_dist, n_x, n_y))

    return distance[-1][-1]


while True:
    test_case += 1

    N = int(input())

    if N == 0:
        break

    cave = [list(map(int, input().split())) for _ in range(N)]

    distance = [[INF] * N for _ in range(N)]

    visited = [[False] * N for _ in range(N)]

    visited[0][0] = True
    distance[0][0] = cave[0][0]

    print(f"Problem {test_case}: {dijkstra(0, 0)}")

Bellman-Ford

μ‚¬μš©λ˜λŠ” 문제 μœ ν˜•

  • 음수 κ°€μ€‘μΉ˜λ₯Ό ν¬ν•¨ν•˜κ³  μžˆλŠ” κ·Έλž˜ν”„μ—μ„œ μ΅œλ‹¨ 거리λ₯Ό κ΅¬ν•˜λŠ” 경우
  • 음수 μ‚¬μ΄ν΄μ˜ 쑴재 μ—¬λΆ€λ₯Ό νŒŒμ•…ν•  수 μžˆλ‹€.

κ΅¬ν˜„ 방법

  1. μ‹œμž‘ λ…Έλ“œ μ„€μ •
  2. 각 λ…Έλ“œμ˜ 거리 값을 λ¬΄ν•œλŒ€λ‘œ μ„€μ •ν•˜κ³  μ‹œμž‘λ…Έλ“œλŠ” 0으둜 μ„€μ •
  3. λ¬΄ν•œλŒ€λ‘œ μ„€μ •λ˜μ–΄ μžˆμ§€ μ•Šμ€ ν˜„μ œ λ…Έλ“œμ—μ„œ λͺ¨λ“  인접 λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ 더 짧은 거리인 경우 값을 κ°±μ‹ 
  4. 3번 과정을 λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•΄ μˆ˜ν–‰
  5. λ…Έλ“œμ˜ 수만큼 μ‹€ν–‰ ν–ˆμ„ λ•Œ 거리가 κ°±μ‹ λœλ‹€λ©΄ 음수 사이클이 μ‘΄μž¬ν•¨μ„ μ•Œ 수 있음
'''
input

3 3
1 2 3
2 3 4
3 1 -8

'''

INF = int(1e9)


def bellman_ford(start):
    distance = [INF] * (V + 1)
    distance[start] = 0

    # ν•œλ²ˆλ” λ°˜λ³΅ν•˜μ—¬ κ°’μ˜ λ³€ν™” μœ λ¬΄μ— 따라 음수 싸이클인지 확인
    for i in range(V):
        for s, e, w in edges:
            if distance[s] != INF and distance[e] > distance[s] + w:
                if i == V - 1:
                    return distance

                distance[e] = distance[s] + w

    return distance


V, E = map(int, input().split())     # N = node, M = edge

edges= []

for _ in range(E):
    s, e, w = map(int, input().split())
    edges.append((s, e, w))

res = bellman_ford(1)
print(res)

# [1000000000, -2, 2, 6]