μ½”λ”© ν…ŒμŠ€νŠΈ/λ°±μ€€

[λ°±μ€€]10971번 'μ™ΈνŒμ› 순회2' 문제 풀이 - JavaScript

μš©λ‡½ 2023. 6. 9. 21:57
λ°˜μ‘ν˜•

[λ°±μ€€]10971번 'μ™ΈνŒμ› 순회2' 문제 풀이 (JavaScript,nodejs)

문제

μ™ΈνŒμ› 순회 λ¬Έμ œλŠ” μ˜μ–΄λ‘œ Traveling Salesman problem (TSP) 라고 λΆˆλ¦¬λŠ” 문제둜 computer science λΆ„μ•Όμ—μ„œ κ°€μž₯ μ€‘μš”ν•˜κ²Œ μ·¨κΈ‰λ˜λŠ” 문제 쀑 ν•˜λ‚˜μ΄λ‹€. μ—¬λŸ¬ 가지 λ³€μ’… λ¬Έμ œκ°€ μžˆμœΌλ‚˜, μ—¬κΈ°μ„œλŠ” κ°€μž₯ 일반적인 ν˜•νƒœμ˜ 문제λ₯Ό μ‚΄νŽ΄λ³΄μž.

1λ²ˆλΆ€ν„° Nλ²ˆκΉŒμ§€ λ²ˆν˜Έκ°€ 맀겨져 μžˆλŠ” λ„μ‹œλ“€μ΄ 있고, λ„μ‹œλ“€ μ‚¬μ΄μ—λŠ” 길이 μžˆλ‹€. (길이 없을 μˆ˜λ„ μžˆλ‹€) 이제 ν•œ μ™ΈνŒμ›μ΄ μ–΄λŠ ν•œ λ„μ‹œμ—μ„œ μΆœλ°œν•΄ N개의 λ„μ‹œλ₯Ό λͺ¨λ‘ 거쳐 λ‹€μ‹œ μ›λž˜μ˜ λ„μ‹œλ‘œ λŒμ•„μ˜€λŠ” 순회 μ—¬ν–‰ 경둜λ₯Ό κ³„νšν•˜λ €κ³  ν•œλ‹€. 단, ν•œ 번 κ°”λ˜ λ„μ‹œλ‘œλŠ” λ‹€μ‹œ 갈 수 μ—†λ‹€. (맨 λ§ˆμ§€λ§‰μ— 여행을 μΆœλ°œν–ˆλ˜ λ„μ‹œλ‘œ λŒμ•„μ˜€λŠ” 것은 μ˜ˆμ™Έ) 이런 μ—¬ν–‰ κ²½λ‘œλŠ” μ—¬λŸ¬ 가지가 μžˆμ„ 수 μžˆλŠ”λ°, κ°€μž₯ 적은 λΉ„μš©μ„ λ“€μ΄λŠ” μ—¬ν–‰ κ³„νšμ„ μ„Έμš°κ³ μž ν•œλ‹€.

각 λ„μ‹œκ°„μ— μ΄λ™ν•˜λŠ”λ° λ“œλŠ” λΉ„μš©μ€ ν–‰λ ¬ W[i][j]ν˜•νƒœλ‘œ 주어진닀. W[i][j]λŠ” λ„μ‹œ iμ—μ„œ λ„μ‹œ j둜 κ°€κΈ° μœ„ν•œ λΉ„μš©μ„ λ‚˜νƒ€λ‚Έλ‹€. λΉ„μš©μ€ λŒ€μΉ­μ μ΄μ§€ μ•Šλ‹€. μ¦‰, W[i][j] λŠ” W[j][i]와 λ‹€λ₯Ό 수 μžˆλ‹€. λͺ¨λ“  λ„μ‹œκ°„μ˜ λΉ„μš©μ€ μ–‘μ˜ μ •μˆ˜μ΄λ‹€. W[i][i]λŠ” 항상 0이닀. κ²½μš°μ— λ”°λΌμ„œ λ„μ‹œ iμ—μ„œ λ„μ‹œ j둜 갈 수 μ—†λŠ” κ²½μš°λ„ 있으며 이럴 경우 W[i][j]=0이라고 ν•˜μž.

Nκ³Ό λΉ„μš© 행렬이 μ£Όμ–΄μ‘Œμ„ λ•Œ, κ°€μž₯ 적은 λΉ„μš©μ„ λ“€μ΄λŠ” μ™ΈνŒμ›μ˜ 순회 μ—¬ν–‰ 경둜λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 λ„μ‹œμ˜ 수 N이 주어진닀. (2 ≤ N ≤ 10) λ‹€μŒ N개의 μ€„μ—λŠ” λΉ„μš© 행렬이 주어진닀. 각 ν–‰λ ¬μ˜ 성뢄은 1,000,000 μ΄ν•˜μ˜ μ–‘μ˜ μ •μˆ˜μ΄λ©°, 갈 수 μ—†λŠ” κ²½μš°λŠ” 0이 주어진닀. W[i][j]λŠ” λ„μ‹œ iμ—μ„œ j둜 κ°€κΈ° μœ„ν•œ λΉ„μš©μ„ λ‚˜νƒ€λ‚Έλ‹€.

항상 μˆœνšŒν•  수 μžˆλŠ” 경우만 μž…λ ₯으둜 주어진닀.

좜λ ₯

첫째 쀄에 μ™ΈνŒμ›μ˜ μˆœνšŒμ— ν•„μš”ν•œ μ΅œμ†Œ λΉ„μš©μ„ 좜λ ₯ν•œλ‹€.

예제 μž…λ ₯ 1

4
0 10 15 20
5 0 9 10
6 13 0 12
8 8 9 0

예제 좜λ ₯ 1

35

πŸ‘‰ 풀이 μ½”λ“œ

const fs = require('fs');
const file = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
const input = fs.readFileSync(file).toString().trim().split('\n');

const n = Number(input[0]);
const graph = input.slice(1).map((line) => line.split(' ').map(Number));
const visited = new Array(n).fill(false);
let min = 1e9;

function dfs(depth, start, cost) {
  if (depth === n - 1 && graph[start][0] !== 0) {
    min = Math.min(min, cost + graph[start][0]);
    return;
  }
  for (let i = 0; i < n; i++) {
    if (!visited[i] && graph[start][i] !== 0) {
      visited[i] = true;
      dfs(depth + 1, i, cost + graph[start][i]);
      visited[i] = false;
    }
  }
}

visited[0] = true;
dfs(0, 0, 0);

console.log(min);

πŸ‘‰ 풀이 ν•΄μ„€

λ³Έ λ¬Έμ œλŠ” 각 νƒμƒ‰λ§ˆλ‹€ κ°€μž₯ μž‘μ€ λΉ„μš©μ„ μ„ νƒν•˜λŠ” λͺ¨λ“  경우의 수λ₯Ό κ³ λ₯΄λŠ” 브루트포슀, λ°±νŠΈλž˜ν‚Ή μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ 문제λ₯Ό ν’€ 수 μžˆλ‹€.

  1. λ¨Όμ € μž…μΆœλ ₯을 λ°›μ•„μ„œ nκ³Ό graph λ°°μ—΄ λ³€μˆ˜μ— λ‹΄μ•„μ£Όμ—ˆλ‹€.
  2. ν•œλ²ˆ λ°©λ¬Έν•œ λ„μ‹œλŠ” μž¬λ°©λ¬Έν•  수 μ—†κΈ° λ•Œλ¬Έμ— λ°©λ¬Έν•œ λ„μ‹œλŠ” λ°©λ¬Έ ν–ˆλ‹€κ³  μ²΄ν¬ν•˜κΈ° μœ„ν•΄μ„œ visitedλΌλŠ” λ°°μ—΄ λ³€μˆ˜λ₯Ό n길이만큼 false둜 μ΄ˆκΈ°ν™”ν•΄μ£Όμ—ˆλ‹€.
  3. μ΅œμ†Œ λΉ„μš©μ„ λ‹΄κΈ° μœ„ν•œ λ°°μ—΄ min λ³€μˆ˜λ₯Ό μ΅œλŒ“κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”ν•΄μ£Όμ—ˆλ‹€.

μ–΄λŠ λ„μ‹œμ—μ„œ μΆœλ°œμ„ ν•˜λ˜μ§€ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν–ˆμ„ λ•Œ 총 이동 λΉ„μš©μ€ κ²°κ΅­ κ°™κΈ° λ•Œλ¬Έμ— 각 λ„μ‹œ 간에 좜발 점을 첫 번째 λ„μ‹œλ₯Ό 좜발점으둜 μž‘μ•˜λ‹€.

즉, graphλ°°μ—΄μ˜ 0번째 μΈλ±μŠ€λΆ€ν„° μΆœλ°œμ„ ν•˜λ„λ‘ ν•΄μ„œ 처음 dfsλ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 visted에 0번째 인덱슀λ₯Ό true둜 μ£Όμ–΄μ„œ μ‹œμž‘μ„ μ•Œλ Έλ‹€.

λ°˜μ‘ν˜•

dfsμ—λŠ” 3개의 λ§€κ°œλ³€μˆ˜κ°€ μžˆλ‹€.

  1. n만큼 λ„μ‹œλ₯Ό μˆœνšŒν•˜κΈ° μœ„ν•œ(depth)
  2. ν˜„μž¬ λ„μ‹œμ—μ„œ λ‹€μŒ λ„μ‹œλ₯Ό 이동할 인덱슀(start)
  3. μ΄λ™ν•˜λ©΄μ„œ λ“œλŠ” λΉ„μš©(cost)

dfsν•¨μˆ˜μ—μ„œ 쀑단점이 제일 μ€‘μš”ν•œλ°, 쀑단점은 κ²°κ΅­ μˆœνšŒμ— λ‹€ λ‹¬μ•˜μ„ λ•Œ μ–΄λ–€ κ²°κ³Ό 값을 κ°€μ§ˆ 것인지λ₯Ό κ²°μ •ν•˜λŠ” 곳이닀.

첫 번째 λ„μ‹œμ—μ„œ μ‹œμž‘ν•˜κ³  κ²°κ΅­ 항상 첫번째 λ„μ‹œλ‘œ λ‹€μ‹œ λŒμ•„μ™€μ•Ό ν•œλ‹€.

depthκ°€ n-1만큼 될 λ•Œ 쀑단 해주도둝 ν•˜κ³  이 μ€‘λ‹¨μ μ—μ„œ 첫 번째둜 λŒμ•„μ˜¬ λ•Œ λΉ„μš©μ„ 더해주면 λœλ‹€.

그리고 처음 dfsλ₯Ό ν˜ΈμΆœν–ˆμ„ λ•Œ λ°”λ‘œ 이 μ€‘λ‹¨μ μœΌλ‘œ λ“€μ–΄κ°€λ©΄ μ•ˆ 되기 λ•Œλ¬Έμ— graph[start][0] 값이 0이 아닐 λ•Œ 쀑단이 될 수 μžˆλ„λ‘ ν•΄μ£Όμ—ˆλ‹€.

결과적으둜 이 μ€‘λ‹¨μ μ—μ„œλŠ” μ΅œμ†Œ λΉ„μš©μ„ ꡬ해야 ν•œλ‹€.

ν˜„μž¬κΉŒμ§€ κ΅¬ν•œ μ΅œμ†Œ λΉ„μš© minκ³Ό ν˜„μž¬κΉŒμ§€ μž¬κ·€λ₯Ό λŒλ©΄μ„œ κ΅¬ν•œ λΉ„μš© cost + 첫 번째둜 λ‹€μ‹œ λŒμ•„κ°ˆ λ•Œμ˜ λΉ„μš©μ„ λΉ„κ΅ν•΄μ„œ 더 μž‘μ€ 값을 min λ³€μˆ˜μ— 담아주도둝 ν•œλ‹€.

 

아직 쀑단될 쑰건이 λ˜μ§€ μ•ŠλŠ” λ‹€λ©΄ for문으둜 κ°€κ²Œ λ˜λŠ”λ°,

μ—¬κΈ°μ„œλŠ” 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜κ±°λ‚˜ λ‹€μŒ λ„μ‹œλ‘œ 이동할 수 있으면(λΉ„μš©μ΄ 0이 μ•„λ‹ˆλ©΄) ν˜„μž¬ 인덱슀λ₯Ό 방문처리 ν•΄μ£Όκ³  dfsν•¨μˆ˜μ— depthλ₯Ό 1 μ¦κ°€μ‹œμΌœ μ£Όκ³  μš°λ¦¬κ°€ λ‹€μŒ κ°€μ•Ό ν•  λ„μ‹œ

즉, ν˜„μž¬ 인덱슀λ₯Ό start둜 μ£Όκ³ , 이동할 λ•Œ λ“œλŠ” λΉ„μš©μ„ λ”ν•΄μ„œ μž¬κ·€ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ μ€€λ‹€.

μˆ˜ν–‰μ΄ λλ‚˜λ©΄ λ°©λ¬Έ 처리λ₯Ό ν•΄μ œν•΄μ£Όλ„λ‘ ν–ˆλ‹€.

 

λ§ˆμ§€λ§‰μœΌλ‘œ μ§€κΈˆκΉŒμ§€ μ΅œμ†Ÿκ°’μ„ κ΅¬ν•œ min을 좜λ ₯ν•΄ 쀌으둜써 ν•΄κ²°ν•΄ 쀄 수 μžˆλ‹€.

λ°˜μ‘ν˜•