일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- BFS
- dfs
- 이분 탐색
- LCA
- 다익스트라
- 오블완
- 하버-보슈법
- union find
- 유니온 파인드
- 내란수괴
- 내란수괴 윤석열
- dfs 백트래킹
- 왈왈왈
- 내란죄
- Prim
- 투 포인터
- 재귀함수
- 알고리즘
- 국민의 힘 뿌리
- 백준
- 분할정복
- 6. 25. 전쟁
- 구조론
- Python
- 티스토리챌린지
- DP
- 프림
- 비상계엄
- 윤석열
- ccw
- Today
- Total
Toolofv 님의 블로그
[Python] 백준 - 11404 플로이드 본문
문제
n(2 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다.
모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 버스의 정보는 버스의 시작 도시 a, 도착 도시 b, 한 번 타는데 필요한 비용 c로 이루어져 있다. 시작 도시와 도착 도시가 같은 경우는 없다. 비용은 100,000보다 작거나 같은 자연수이다.
시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다.
출력
n개의 줄을 출력해야 한다. i번째 줄에 출력하는 j번째 숫자는 도시 i에서 j로 가는데 필요한 최소 비용이다. 만약, i에서 j로 갈 수 없는 경우에는 그 자리에 0을 출력한다.
문제해결방법 -
1. 플로이드 와샬 알고리즘이라고 하는 방법을 활용해야 하는데, 전 포스팅인 벨만포드알고리즘 문제처럼 금방 떠올려서 해결할 수 있는 문제는 아닌 것 같고, 그렇다고 백지부터 조금씩 퍼즐을 맞추고, 참고하여 풀기에는 부적절하다.
2. 코드를 보며, 3중 for문과 원리를 이해하도록 하자. 코드는 엄청 간단한데 헷갈린다. ;
피상적으로는 이해되는데, 정확한 작동 원리는 아직도 헷갈린다..;
3. for문의 의미.
1) 첫번째 for문의 반복되는 인덱스는 중간 경유지이다.
2) 두번째, 세번째의 인덱스는 시작점과 도착점이다.
4. 경유지를 고정해놓고, 모든 dp를 돌고, 그다음 경유지 고정해놓고 모든 dp를 돌아 최소값으로 반영한다.
헷갈리는 점-
ex)
[1]과 [5] 사이의 최소값이라면 [1][2] +[2][5] ~ [1][4] + [4][5] 중 최소값이 존재할텐데,
[1][2]의 최소값은 또 [1][5]+ [5][2]이 될 수도 있다는 것 때문에 반영이 안되는 경우가 있지 않을까 생각이 들었고, 명확하게 정리가 되지 않았다. 또 [1][5]는 [1][?] + [?][5] 로 계속 반복될 수도 있지 않을까 하는 수렁ㅠㅠ
일단 잠정적으로 내린 결론(너무 복잡하게 생각하는 것일 수도 있다. 귀납적으로 하나하나 검토해보면 뭔가 알 수도 있을 것 같긴 한데, 일단 아래와 같게 생각하였다. 수학적으로 딱 떨어지는 연역의 과정은 아닐 수도 있다..)
-> [1][2] + [2][5] 의 경우라면 모든 노드를 한번씩 거친 것이 최소값이 될 수도 있을 것이다.
-> 여기서 [1][2]의 최소값이 [1][5]+[5][2] 일리는 없다. 원래 [1][5]의 최소값을 구하고 있었다.;
-> 그래도 만약 [1][2] 의 최소값을 구하는 경로가 [1]-[5]-[3]-[2] 라면 [1][3]의 사이의 k = 5가 마지막에 반영될 수도 있지만,
([1][5][3]) + [2] = [1] + ([5][3][2]) 와 같을 것이기 때문에 [5]가 갑자기 마지막에 최소값 반영되어 전부 다시 해야하는 경우는 없을 것이란 결론이다. 어떤 경로가 고정되어 있으면 for문을 돔에 따라 위 괄호가 계속 바뀌어서, 누락될 염려는 없다.
import sys
from collections import deque
import heapq
sys.setrecursionlimit(10**8)
input = sys.stdin.readline
n = int(input())
m = int(input())
INF = sys.maxsize
dp = [[INF for _ in range(n+1)] for _ in range(n+1)]
for _ in range(m):
a, b, c = map(int, input().split())
dp[a][b] = min(dp[a][b], c)
for i in range(1, n+1):
dp[i][i] = 0
for k in range(1, n+1): # 1 2 3 4 5
for i in range(1, n+1):
for j in range(1, n+1):
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j])
for i in range(1, n+1):
for j in range(1, n+1):
if dp[i][j] == INF:
print(0, end=' ')
else:
print(dp[i][j], end=' ')
print()
'Algorithm' 카테고리의 다른 글
[Python] 백준 1806 - 부분합 (0) | 2024.06.18 |
---|---|
[Python] 백준 - 2470 두 용액 (0) | 2024.06.18 |
[Python] 백준 - 9370 미확인 도착지 (1) | 2024.06.14 |
[Python] 백준 - 13549 숨바꼭질 3 (1) | 2024.06.14 |
[Python] 백준 - 1504 특정한 최단 경로 (0) | 2024.06.14 |