합승 택시 요금 javascript

HyosikPark·2021년 4월 2일
0

알고리즘

목록 보기
72/72
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값이 최소비용이 됩니다.

0개의 댓글