알고리즘 특강 Week8: 최단경로 - 플로이드 와샬/다익스트라
최단경로 유형
- 플로이드 와샬 알고리즘
- 모든 노드를 방문하는 최단경로(최소비용경로) 도출
- 다익스트라 알고리즘
- 특정 노드에서 다른 노드까지의 최단경로(최소비용경로) 도출
플로이드 와샬 알고리즘 구현방법
알고리즘 순서
-
방문배열과 비용배열을 생성한다.
-
방문배열은 방문하였을 시 True, 아직 방문하지 않았다면 False를 값으로 갖는다.
-
비용배열은 표현가능한 최대값을 모든 점에 미리 배정한다.
-
-
첫 시작점을 잡는다.
- 해당 점의 방문배열은 True, 비용배열은 0으로 설정한다.
-
첫 시작점과 연결된 점들의 비용배열에, 연결된 경로의 비용을 각각 담는다.
- 연결된 점들 중 최소비용경로를 선택하고 그 점을 방문한다.
- 다음 방문된 점의 방문배열을 True로 바꾸고 또다시 비용배열에 연결경로의 비용을 담는다.
- 이 때, 기존에 비용이 담겨있는 점들의 경우 새로 입력되는 비용과 비교하여 최소값으로 갱신한다.
- 비교 결과, 연결된 점들 중 최소의 비용값으로 방문할 수 있는 점을 다음 점으로 지정한다.
- 다음 점에 대하여 4 과정을 반복한다.
- 마지막 점까지 방문한 뒤, 비용 배열의 합을 구해주면 플로이드 와샬 알고리즘에 의한 전체 점을 잇는 최소비용경로를 도출할 수 있다.
코드
# costs: 연결된 노드 간 경로 및 비용을 담은 배열
# ex. [(노드1, 노드2, 비용), ...]
visited = [False for i in range(n)] # 방문배열
values = [2**31 - 1 for i in range(n)] # 비용배열
# 초기 점 설정
start = 0
visited[start] = True
values[start] = 0
while False in visited:
# 노드 완전탐색으로 비용배열의 거리값 최소화
for i in costs:
if(visited[i[1]]==False and i[0]==start):
values[i[1]] = min(values[i[1]], i[2])
if(visited[i[0]]==False and i[1]==start):
values[i[1]] = min(values[i[0]], i[2])
refer = 2**31 - 1
# 방문하지 않은 노드 중 최소비용 노드 위치 탐색
for i in range(n):
if(visited[i]==False and values[i]!=0):
refer = min(refer, values[i])
answer += refer
# 해당 노드 방문여부 체크, 그 노드로 이동해서 다시 반복문 실행
for i in range(n):
if(visited[i]==False and values[i]!=refer):
visited[i] = True
start = i
break
다익스트라 알고리즘 구현방법
알고리즘 순서
-
방문배열과 비용배열을 생성한다.
-
방문배열은 방문하였을 시 True, 아직 방문하지 않았다면 False를 값으로 갖는다.
-
비용배열은 표현가능한 최대값을 모든 점에 미리 배정한다.
-
-
첫 시작점을 잡는다.
- 해당 점의 방문배열은 True, 비용배열은 0으로 설정한다.
-
첫 시작점과 연결된 점들의 비용배열에, 연결된 경로의 비용을 각각 담는다.
- 위의 비용 중 최소비용경로를 선택하고 그 점을 방문한다.
- 다음 방문된 점의 방문배열을 True로 바꾸고 또다시 비용배열에 연결경로의 비용을 담는다.
- 이 때, 지금 방문한 점까지 오기 위해 소요된 비용누적값을 새로 연결될 수 있는 비용에 더하여 기존값과 비교, 최소값으로 갱신해야 한다.
- 이후, 현재 방문하지 않은 점들 중 최소비용값으로 방문할 수 있는 점을 다음 점으로 지정한다.
- 다음 점에 대하여 4 과정을 반복한다.
- 모든 점에 대하여 탐색이 마쳐지면(즉, 더이상 방문하지 않은 점이 없다면) 첫 시작점을 기준으로 특정 점에 도달하는데 드는 최소비용값이 비용배열에 나타난다.
import sys
# costs: 연결된 노드 간 경로 및 비용을 담은 배열
# ex. [(노드1, 노드2, 비용), ...]
visited = [False for _ in range(n)] # 방문배열
values = [sys.maxsize for _ in range(n)] # 비용배열
# 0번 노드를 출발점으로 설정
visited[0] = True
values[0] = 0
length = len(visited)
while False in visited:
checkLoc = -1
checkValue = sys.maxsize
# 미방문한 노드 중 최솟값 찾기
for i in range(length):
if visited[i]==False and values[i]<checkValue:
checkLoc = i
checkValue = values[i]
# 모든 점을 방문했다면 반복문 탈출
if checkLoc = -1:
break
# 경로 완전탐색으로 비용배열 수정
visited[checkLoc] = True
for v1, v2, c in costs:
if v1==checkLoc and visited[v2]==False:
values[v2] = min(values[v2], values[v1]+c)
if v2==checkLoc and visited[v1]==False:
values[v1] = min(values[v1], values[v2]+c)
Leave a comment