일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Mask Processing
- DP
- C++
- MinHeap
- two-stage detector
- eecs 498
- opencv
- 딥러닝
- deep learning
- AlexNet
- dynamic programming
- machine learning
- image processing
- object detection
- 그래프 이론
- LSTM
- 머신러닝
- r-cnn
- One-Stage Detector
- 강화학습
- MySQL
- YoLO
- real-time object detection
- ubuntu
- dfs
- 백준
- CNN
- Reinforcement Learning
- Python
- BFS
- Today
- Total
JINWOOJUNG
[ DP - 11404 ] 플로이드(C++) 본문


접근법
최단경로 찾기에 적용 가능한 Dynamic Programming Algorithm이 바로 Floyd(플로이드)이다.
문제를 보면 특정 도시에서 다른 도시로 가는 서로다른 비용을 가지는 버스가 존재하고, 특정 도시에서 다른 도시로 가는 최소 비용을 구하는 문제이다. 따라서 주어진 문제(경로에 따른 비용)에 대하여 하나 이상의 많은 해가 존재할 때, 최적의 해답을 찾아야 하는 최적화 문제이다.
우리는 주어진 정보 중 출발 도시와 도착 도시 사이의 최소 cost를 원소로 가지는 인접 행렬식 W를 포현할 수 있다. 예를들어, W[i][j]& 는i에서j로가는최소비용을의미한다.만약i에서j로가는버스가없다면,구해야하는것은최소비용이기때문에무한대로표현하고,i==j$이면 0으로 설정해야 한다.
그렇다면 우리가 고려해야 하는 것은 결국 i에서 j로 바로 가는 비용과, 1≤k≤n(n은 도시의 수) 범위의 k에 대하여 i에서 k로 간 뒤, k에서 j로 가는 비용을 비교하면 된다. 이러한 최소 비용을 저장하는 Matrix를 Dk,1≤k≤n이라 한다.

다음과 같이 문제가 주여졌다고 하자. i번째 도시를 Vi로 표현하여 각 그래프의 노드로 나타냈으며, 각 도시간 이동에 필요한 비용을 간선으로 표현하였다. W Matrix를 구하면 다음과 같다.

k 도시를 거쳤을 때를 고려한 최소 비용을 나타내는 그래프는 Dk이므로, 결국 D0=W,Dn=D가 될 것이다. 따라서 D를 구하기 위해서는 D0를 이용하여 Dn을 구하는 방법을 고안해야 한다.
앞에서 이미 재귀 관계식을 도출하기 위한 관계를 말로 설명하였다.
우리가 고려해야 하는 것은 결국 i에서 j로 바로 가는 비용과, 1≤k≤n(n은 도시의 수) 범위의 k에 대하여 i에서 k로 간 뒤, k에서 j로 가는 비용을 비교하면 된다.
따라서 이를 수식화 한다면 아래와 같다.
Dk[i][j]=minimum(Dk−1[i][j],Dk−1[i][k]+Dk−1[k][j])
이제 구현 해 보자.
정답
#pragma warning(disable:4996)
#include <iostream>
#include <cstdlib>
#define C_INFINITE 100000000 // 매우 큰 값
using namespace std;
int DP[101][101];
int main() {
int n, m, i, j, k;
int cin1, cin2, cost;
scanf("%d %d", &n, &m);
// i == j -> 내가 내 위치로 가는 과정 -> 0
// 아니면 무한대로 설정 -> Minimum Cost를 구해야 하기 때문
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
DP[i][j] = (i == j) ? 0 : C_INFINITE;
}
}
// i->j로 가는 버스의 cost로 갱신
for (i = 0; i < m; i++) {
scanf("%d %d %d", &cin1, &cin2, &cost);
if (DP[cin1][cin2] > cost)
DP[cin1][cin2] = cost;
}
// D^1~D^n 계산
for (k = 1; k <= n; k++) {
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
DP[i][j] = (DP[i][j] < (DP[i][k] + DP[k][j])) ? DP[i][j] : DP[i][k] + DP[k][j];
}
}
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (DP[i][j] == C_INFINITE)
DP[i][j] = 0;
printf("%d ", DP[i][j]);
}
printf("\n");
}
return 0;
}
결국, 앞서 언급한 점화식은 아래와 같이 구현할 수 있다.
for (k = 1; k <= n; k++) {
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
DP[i][j] = (DP[i][j] < (DP[i][k] + DP[k][j])) ? DP[i][j] : DP[i][k] + DP[k][j];
}
}
}
k에 대한 for문이 가장 바깥쪽에서 고려되어야 정확한 계산이 가능함을 주의하자.
위 문제에 대한 실행 결과

다음과 같이 각 도시에 대하여 이동했을 때의 최소 비용은 문제와 같다.
백준 문제에 대한 정답은

다음과 같이 잘 나옴을 확인할 수 있다.
'백준' 카테고리의 다른 글
[ DP ] Dijkstra Algorithm (0) | 2024.05.25 |
---|---|
[ DP ] 조약돌 놓기(C++) (0) | 2024.05.24 |
[ DP - 12865 ] 평범한 배낭(C++) (0) | 2024.05.20 |
[ DP-11049 ] 행렬 곱셈 순서(C++) (0) | 2024.05.19 |
[ 정렬 - 24174 ] 알고리즘 수업 - 힙 정렬 2(C++) (0) | 2024.04.03 |