외판원 문제(travelling salesman problem, 이하 TSP)는 아래와 같이 정의됩니다.
각 도시의 위치를 나타내는 좌표평면 위의 점들을 입력받아, TSP의 최단 거리를 리턴해야 합니다.
places[i]
는 number
타입을 요소로 갖는 배열places[i].length
는 2places[i]
의 요소는 차례대로 좌표평면 위의 y좌표, x좌표number
타입을 리턴해야 합니다.calculateDistance
가 주어집니다. 도시 간 거리는 반드시 이 함수를 이용해서 계산해야 합니다.calculateDistance
는 소수점 계산을 피하기 위해 두 점 사이의 거리에 100을 곱한 후 정수 부분만 취합니다. 최단 거리도 이 기준으로 판단합니다.let placesToVisit = [
[0, 0],
[1, 1],
[1, 3],
[2, 2],
];
let output = TSP(placesToVisit);
console.log(output); // --> 423
// 방문 순서: [0, 0], [1, 1], [2, 2], [1, 3]
placesToVisit = [
[0, 0],
[3, 3],
[-3, 3],
[2, 3],
[1, 3],
];
output = TSP(placesToVisit);
console.log(output); // --> 940
// 방문 순서: [-3, 3], [1, 3], [2, 3], [3, 3], [0, 0]
순열.
function calculateDistance(p1, p2) {
const yDiff = p2[0] - p1[0];
const xDiff = p2[1] - p1[1];
return Math.sqrt(Math.pow(yDiff, 2) + Math.pow(xDiff, 2)) * 100;
}
const TSP = function (places) {
const getPermutations = function (arr, len) {
const results = [];
if (len === 1) return arr.map((el) => [el]);
arr.forEach((fixed, idx, origin) => {
const rest = [...origin.slice(0, idx), ...origin.slice(idx + 1)]
const permutations = getPermutations(rest, len - 1);
const attached = permutations.map((el) => [fixed, ...el]);
results.push(...attached);
});
return results;
};
let cities = getPermutations(places, places.length)
let result = Number.MAX_SAFE_INTEGER
for (let i = 0; i < cities.length; i++) {
let distance = 0
for (let j = 0; j < cities[i].length - 1; j++) {
distance += parseInt(calculateDistance(cities[i][j], cities[i][j + 1]))
}
if (distance < result) result = distance;
}
return result
};