모든 노드 간의 최소의 경로를 알아야 하므로 플로이드 워셜로 접근해야 한다.
플로이드 워셜 문제이다.
최대값 설정하는 것이 중요하다.
: 문제에서 100000이 제한값이라고 해서 100001이라고 설정했는데,
76점이 나왔다.
경유했을때 갈수없는 값도 2000만 보다 작다면
비교시 2000만이 나와야 하는데, 그보다 작은 값이 dp테이블에 저장될 것이므로
최대값을
두 군데 모두 고려해야 한다.
#include <string>
#include <vector>
using namespace std;
int solution(int n, int s, int a, int b, vector<vector<int>> fares) {
int answer = 0;
vector<vector<int>>dp(n, vector<int>(n, 2000001));
//놓친 부분
for(int i = 0; i < n;i++)
{
for(int j = 0; j < n;j++)
{
if(i == j)
dp[i][j] = 0;
}
}
for(int i = 0; i < fares.size(); i++)
{
dp[fares[i][0] - 1][fares[i][1] -1] = fares[i][2];
//놓친 부분
dp[fares[i][1] - 1][fares[i][0] -1] = fares[i][2];
}
//경유하는 점.
for(int k = 0; k < n; k++)
{
//시작점
for(int i = 0; i < n; i++)
{
//종점
for(int j = 0; j < n; j++)
{
dp[i][j] = min(dp[i][k] + dp[k][j] , dp[i][j]);
}
}
}
s -= 1;
a -= 1;
b -= 1;
answer = 2000001;
//반환값은 출발지에서 a까지의 값 + 출발지에서 b까지의 값이다.
//예시 2번을 보면 경유해서 간다.
//근데 최소값을 구하는 것이므로 경유해서 갈때에 대한 것을 고려할 수 있다.
for(int k = 0; k < n; k++)
{
answer = min(answer, dp[s][k] + dp[k][a] + dp[k][b]);
}
return answer;
}
dp[s][a] + dp[s][b]를 하게 되면 7 + 7 + 11 이 나온다.
경유하는 구간이 dp[s][b] 이므로 이를 처리하기 위해서는
경유할때의 식을 다시 한 번 더 사용하면 된다.
//반환값은 출발지에서 a까지의 값 + 출발지에서 b까지의 값이다.
//예시 2번을 보면 경유해서 간다.
//근데 최소값을 구하는 것이므로 경유해서 갈때에 대한 것을 고려할 수 있다.
for(int k = 0; k < n; k++)
{
answer = min(answer, dp[s][k] + dp[k][a] + dp[k][b]);
}
요거를 어떻게 생각해 낼수 있냐면 3번 예제를 통해 고찰할 수 있다.
s -> b로 s - > a로 가는데 그대로 사용하면 7 + 7 + 11 -> 25이다.
시작점에서 경유점으로, 그리고 경유점에서 a와 b로 이동하는 것이
최저 비용으로 나타낼수 있따.