function solution(n, s, a, b, fares) {
const path = Array.from({length: n}, (_,i) =>
Array.from({length: n}, (_,j) => i === j ? 0 : Infinity));
fares.forEach(([from,to,fee]) => {
path[from-1][to-1] = fee;
path[to-1][from-1] = fee;
})
for (let mid = 0; mid < n; mid++) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
path[i][j] = Math.min(path[i][j], path[i][mid] + path[j][mid]);
}
}
}
let min = Infinity
for (let k = 0; k < n; k++) {
min = Math.min(min, path[s-1][k] + path[k][a-1] + path[k][b-1]);
}
return min;
}
Floyd–Warshall 알고리즘을 사용한 해결방법입니다.
먼저 2차원 배열을 생성합니다. 2차원 배열의 [i][j]는 i에서 j까지 가는 경우의 비용을 의미합니다.
const path = Array.from({length: n}, (_,i) =>
Array.from({length: n}, (_,j) => i === j ? 0 : Infinity));
console.log(path);
/* [
[ 0, Infinity, Infinity, Infinity, Infinity, Infinity ],
[ Infinity, 0, Infinity, Infinity, Infinity, Infinity ],
[ Infinity, Infinity, 0, Infinity, Infinity, Infinity ],
[ Infinity, Infinity, Infinity, 0, Infinity, Infinity ],
[ Infinity, Infinity, Infinity, Infinity, 0, Infinity ],
[ Infinity, Infinity, Infinity, Infinity, Infinity, 0 ]
] */
i와 j가 일치하는 경우는 자기 자신의 위치에서 자신의 위치로 가는 경우, 즉 제자리입니다. 따라서 요금은 0원입니다.
그리고 나머지는 아직까지 비용을 알 수 없기 때문에 Infinity로 처리해줍니다.
다음으로 문제에서 제시된 경로사이에 요금을 구합니다.
fares.forEach(([from,to,fee]) => {
path[from-1][to-1] = fee;
path[to-1][from-1] = fee;
})
console.log(path);
/*
[
[ 0, Infinity, 41, 10, 24, 25 ],
[ Infinity, 0, 22, 66, Infinity, Infinity ],
[ 41, 22, 0, Infinity, 24, Infinity ],
[ 10, 66, Infinity, 0, Infinity, 50 ],
[ 24, Infinity, 24, Infinity, 0, 2 ],
[ 25, Infinity, Infinity, 50, 2, 0 ]
]
*/
i에서 j로 가던 j에서 i로 가던 비용은 같기 때문에 동일한 요금을 책정합니다. 실제 위치보다 index는 하나 더 작기 때문에, 즉 1번 위치는 0번 인덱스이기 때문에 각 위치에서 -1을 한 뒤에 요금을 책정합니다.
다음으로는 여러번의 이동을 거쳐 도달해야하는 경로의 경우 최단거리를 구하기 위해서 이동할 수 있는 경우의 수를 모두 따져봐야합니다.
i에서 임의의 지점 mid를 거쳐 j로 가는 모든 경우의 수를 구하면서 최솟값을 찾아 줍니다.
for (let mid = 0; mid < n; mid++) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
path[i][j] = Math.min(path[i][j], path[i][mid] + path[j][mid]);
}
}
}
console.log(path);
/*
[
[ 0, 63, 41, 10, 24, 25 ],
[ 63, 0, 22, 66, 46, 48 ],
[ 41, 22, 0, 51, 24, 26 ],
[ 10, 66, 51, 0, 34, 35 ],
[ 24, 46, 24, 34, 0, 2 ],
[ 25, 48, 26, 35, 2, 0 ]
]
*/
이제 각 지점까지의 최소비용은 알고 있는 상태입니다.
우리는 특정한 위치 s에서 a 또는 b로 도달해야합니다.
이때 어느지점까지는 함께 탑승할 수도 있고, 완전히 따로 갈 수도 있기 때문에 최소비용이 나오는 경우를 찾아야 합니다.
s에 k지점까지는 같이 탑승하고, k 지점에서 a까지, k 지점에서 b까지 따로 탑승하는 모든 경우의 수들 중 최솟값을 구합니다.
let min = Infinity
for (let k = 0; k < n; k++) {
min = Math.min(min, path[s-1][k] + path[k][a-1] + path[k][b-1]);
}
return min
여기서 min값이 최소비용이 됩니다.