1. 플로이드 워셜 알고리즘의 개념
- 모든 노드에서 다른 노드 까지의 최단거리 경로를 모두 계산
- 다익스트라 알고리즘과 마찬가지로 단계별로 거쳐가는 노드를 기준으로 알고리즘을 수행
- 하지만 매단계마다 방문하지 않은 노드중에 최단거리를 갖는 노드를 찾는 과정이 필요하지 않음
- 플로이드 워결은 2차원 테이블에 최단거리 정보를 저장
- 플로이드 워셜 알고리즘은 다이나믹 프로그래밍 유형에 속함
2. 알고리즘의 작동원리
- DP 기반의 알고리즘으로 점화식을 사용
- 각 단계마다 특정한 노들 k를 거쳐가는 경우를 확인
- a 에서 b로 가는 최단거리보다 a 에서 k를 거쳐가는 b로 가는 거리가 더 짧은지 검사
- 점화식

- 초기 상태에서는 그래프의 인접 행렬을 배열로 설정하며 자기 자신으로 가는 경로는 0으로 초기화 함
3. 플로이드 워셜 알고리즘의 단계
- 초기화
- 주어진 그래프의 가중치 행렬을 기반으로 배열을 초기화.
- 자기자신으로 가는 경로는 0으로 연결되지 않는 경로는 무한대로 설정
- 점화식 계산
- 모든 정점 k에 대해 점화식을 반복
dist[i][j] = min(dist[][i]j, dist[i][k] + dist[k][j])
- 음수 사이클 검사
- 계산이 끝난후 배열의 대각선 원소
dist[i][i]
를 확인
- 만약
dist[i][i]
< 0 인경우 정점 i 에서 시작하여 다시 정점 I로 돌아오는 경로에 음수 사이클이 존재한다는 것을 의미
- 음수 사이클이 존재하면 최단 경로가 무의미 하므로 이에대한 예외처리가 필요
4. 구현 코드
import java.util.Arrays;
public class FloydWarshall {
static final int INF = 1000000; // 무한대를 표현하기 위한 큰 값
public static void floydWarshall(int[][] graph) {
int n = graph.length;
int[][] dist = new int[n][n];
// 거리 배열 초기화
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = graph[i][j];
}
}
// 플로이드 워셜 점화식 적용
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][k] != INF && dist[k][j] != INF) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
// 결과 출력
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][j] == INF) {
System.out.print("INF ");
} else {
System.out.print(dist[i][j] + " ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] graph = {
{0, 3, INF, INF},
{2, 0, INF, INF},
{INF, 7, 0, 1},
{6, INF, INF, 0}
};
floydWarshall(graph);
}
}
5. 시간 복잡도
- 시간 복잡도는 N^3 임 따라서 노드의 수가 적을때 사용해야함
- 코딩테스트 문제에서는 보통 노드의 수를 500 이하로줌
6. 실제로 어쩔떄 쓰일까?
- 네트워크 라우팅 : 데이터 패킷 전송의 최적 경로를 계산
- 교통망 분석 : 도시간의 최단 이동 경로 계산
- 게임 계발 : 맵에서 NPC 간의 이동경로 계산