AI 그게 뭔데
끄적끄적 개발일지
AI 그게 뭔데
전체 방문자
오늘
어제
  • 분류 전체보기 (342)
    • 논문 (5)
    • DL(Deep-Learning) (34)
      • 개념 (14)
      • Python 기초 (14)
      • Tensorflow (6)
      • Pytorch (0)
    • NLP (10)
    • OpenCV (53)
    • DevOps (10)
      • AWS (2)
      • Docker & Kubernetes (4)
      • Spark (3)
      • SQL (1)
    • MacOS (1)
    • React-Native (2)
    • BI (3)
      • GA(Google Analytics) (3)
      • Tableau (0)
    • 알고리즘 (221)
      • 백준 (76)
      • 프로그래머스 (108)
      • 기타 알고리즘 (37)

인기 글

태그

  • 알고리즘
  • level1
  • OpenCV
  • 연습문제
  • 이코테
  • 프로그래머스
  • Python
  • LEVEL2
  • 백준
  • 파이썬

최근 글

hELLO · Designed By 정상우.
AI 그게 뭔데

끄적끄적 개발일지

최단 경로 (Shortest Path Problem) - 플로이드 워셜 알고리즘
알고리즘/기타 알고리즘

최단 경로 (Shortest Path Problem) - 플로이드 워셜 알고리즘

2022. 1. 24. 21:59

플로이드 워셜 최단 거리 알고리즘

  • 모든 노드에서 다른 모든 노드까지의 최단 경로를 모두 계산한다
  • 플로이드 워셜(Floyd-Warshall) 알고리즘은 다익스트라 알고리즘과 마찬가지로 단계별로 거쳐 가는 노드를 기준으로 알고리즘을 수행한다
    • 다만 매 단계마다 방문하지 않은 노드 중에 최단 거리를 갖는 노드를 찾는 과정이 필요하지 않다
  • 플로이드 워셜은 2차원 테이블에 최단 거리 정보를 저장한다
  • 플로이드 워셜 알고리즘은 다이나믹 프로그래밍 유형에 속한다
  • 각 단계마다 특정한 노드 𝑘를 거쳐 가는 경우를 확인한다
    •  𝑎에서 𝑏로 가는 최단 거리보다 𝑎에서 𝑘를 거쳐 𝑏로 가는 거리가 더 짧은지 검사한다
  • 시간 복잡도는 O($N^3$) → N번의 단계 마다 O($N^2$)의 연산을 통해 현재 거쳐가는 모든 경로 고려

 

점화식은 다음과 같다.

 

 

✔ 플로이드 워셜 알고리즘 동작 과정

[초기 상태] 그래프를 준비하고 최단 거리 테이블을 초기화

  • 연결된 간선은 단순히 그 값을 채워 넣고, 연결  되지 않은 간선은 무한 값을 넣습니다.

 

 Step 1   1번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다

 

 

$D_{ab}$  :  a에서 b로 가는 최소 비용
               a→b 의 최소 비용은 a에서 b로 바로 가는 비용과 k를 거쳐서, 즉 a→k→b의 비용 중 작은 값이다.

 

⭐ 점화식  :  $D_{ab} = min(D_{ab} , D_{a1} + D_{1b})$

 

$D_{23} = min(D_{23} , D_{21} + D_{13})$

$D_{24} = min(D_{24} , D_{21} + D_{14})$

$D_{32} = min(D_{32} , D_{31} + D_{12})$

$D_{34} = min(D_{34} , D_{31} + D_{14})$

$D_{42} = min(D_{42} , D_{41} + D_{12})$

$D_{43} = min(D_{43} , D_{41} + D_{13})$

 

1을 거쳐 갈 때가 더 빠른 경우가 존재한다면 빠른 경우로 최단 거리를 갱신하는 식

 

 

 Step 2  2번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다

 

 

⭐ 점화식  :  $D_{ab} = min(D_{ab} , D_{a2} + D_{2b})$

 

$D_{13} = min(D_{13} , D_{12} + D_{23})$

$D_{14} = min(D_{14} , D_{12} + D_{24})$

$D_{31} = min(D_{31} , D_{32} + D_{22})$

$D_{34} = min(D_{34} , D_{32} + D_{24})$

$D_{41} = min(D_{41} , D_{42} + D_{22})$

$D_{43} = min(D_{43} , D_{42} + D_{23})$

 

2번 노드를 거쳐 가는 경우, 2번 노드를 제외한 1번, 3번, 4번 노드에서 2개의 노드를 뽑는 경우를 고려한다.

 

 

 Step 3  3번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다

 

 

⭐ 점화식  :  $D_{ab} = min(D_{ab} , D_{a3} + D_{3b})$

 

$D_{12} = min(D_{12} , D_{13} + D_{32})$

$D_{14} = min(D_{14} , D_{13} + D_{34})$

$D_{21} = min(D_{21} , D_{23} + D_{31})$

$D_{24} = min(D_{24} , D_{23} + D_{34})$

$D_{41} = min(D_{41} , D_{43} + D_{31})$

$D_{42} = min(D_{42} , D_{43} + D_{32})$

 

3번을 제외하고 1번, 2번, 4번 중에서 두 쌍을 선택하는 경우는 (1,2), (1,4), (2,1), (2,4), (4,1), (4,2) 로 6가지 경우가 있다.

갱신되는 식에 대하여 $_3P_2 = 6$ 에 대한 수식이 만들어 지게 되며, 결국 $_{N-1}P_{2}$ 개의 쌍을 단계마다 반복해서 확인하고 있다.

 

 

 Step 4   4번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다

 

 

⭐ 점화식  :  $D_{ab} = min(D_{ab} , D_{a4} + D_{4b})$

 

$D_{12} = min(D_{12} , D_{14} + D_{42})$

$D_{13} = min(D_{13} , D_{14} + D_{43})$

$D_{21} = min(D_{21} , D_{24} + D_{41})$

$D_{23} = min(D_{23} , D_{24} + D_{43})$

$D_{31} = min(D_{31} , D_{34} + D_{41})$

$D_{32} = min(D_{32} , D_{34} + D_{42})$

 

 

[최종 결과]

 

 

 

✔ 구현

입력예시

더보기

4

7

1 2 4

1 4 6

2 1 3

2 3 7

3 1 5

3 4 4

4 3 2

 

출력예시

더보기

0 4 8 6

3 0 7 9

5 9 0 4

7 11 2 0

 

첫번째, 두번째의 n,m 은 노드의 개수와 간선의 개수
세 번째 줄 부터는 시작 노드 , 도착 노드 , 소모 거리

 

INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정

n, m = map(int, input().split()) #노드 개수, 간선 개수

# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
graph = [[INF] * (n + 1) for _ in range(n + 1)]

# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
for a in range(1, n + 1):
    for b in range(1, n + 1):
        if a == b:
            graph[a][b] = 0

# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
for _ in range(m):
    # A에서 B로 가는 비용은 C라고 설정
    a, b, c = map(int, input().split())
    graph[a][b] = c

# 점화식에 따라 플로이드 워셜 알고리즘을 수행
for k in range(1, n + 1):
    for a in range(1, n + 1):
        for b in range(1, n + 1):
            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])

# 수행된 결과를 출력
for a in range(1, n + 1):
    for b in range(1, n + 1):
        # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
        if graph[a][b] == 1e9:
            print("INFINITY", end=" ")
        # 도달할 수 있는 경우 거리를 출력
        else:
            print(graph[a][b], end=" ")
    print()

 

'알고리즘 > 기타 알고리즘' 카테고리의 다른 글

[그리디 Greedy] 문자열 뒤집기  (0) 2022.01.24
[그리디 Greedy] 모험가 길드  (0) 2022.01.24
재귀함수 Recursion Funtion  (0) 2022.01.24
최단 경로 (Shortest Path Problem) : 다익스트라 알고리즘  (0) 2022.01.24
[이것이 코딩 테스트다 with Python] 개미 전사 : Dynamic Programming  (0) 2022.01.24
    AI 그게 뭔데
    AI 그게 뭔데
    공부와 개발 그리고 AI가 약간 첨가된 흔적 남기기

    티스토리툴바