1 분 소요



https://www.acmicpc.net/problem/10971



🔍 문제 풀이

외판원이 모든 도시를 한 번씩 방문하고, 다시 출발점으로 돌아올 때의 가장 짧은 경로를 찾는 문제

💫 트러블슈팅

TSP는 사이클을 구하는 문제라 시작점을 바꿔도 최소 비용은 동일

  • 0 → 1 → 2 → 3 → 0 경로의 총 비용과 1 → 2 → 3 → 0 → 1 경로의 총 비용은 같음
  • 시작점만 다를 뿐, 같은 순환 경로이기 때문


처음엔 dfs를 아래와 같이 호출

for (int i = 1; i < n; i++) {
    v[i] = true;
    dfs(1, 0, 0);
}

하지만 아래처럼 시작점을 0으로 고정해도 최소 비용은 변하지 않음

v[0] = true; // 시작 도시 고정
dfs(1, 0, 0);


모든 도시를 한 번씩만 탐색

따라서 0 → 1 → 2 → 3 → 2 → 1 → 0 이런 경로는 불가

` 0 → 1 → 2 → 3 → 0, 0 → 1 → 3 → 2 → 0, 0 → 2 → 1 → 3 → 0` 등 모든 가능한 순열을 탐색하며 최종적으로 가장 짧은 사이클을 찾아냄


💻 코드

  • cur은 arr 배열의 행 인덱스로, 현재 위치한 도시를 나타낸다.
  • 반복문의 jarr 배열의 열 인덱스로, 다음으로 이동할 도시를 나타낸다.
import java.io.*;
import java.util.*;

public class Main {
    static int n;
    static int[][] arr;
    static boolean[] v;
    static int ans = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        arr = new int[n][n];
        v = new boolean[n];

        for (int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            for (int j = 0; j < n; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        v[0] = true;
        dfs(1, 0, 0);

        System.out.println(ans);
    }

    static void dfs(int depth, int cur, int sum){
        // 1. 종료조건
        if(depth == n){
            if (arr[cur][0] != 0) {
                ans = Math.min(ans, sum + arr[cur][0]);
            }
            return;
        }

        // 2. dfs 호출
        for(int j = 0; j<n; j++){
            if(arr[cur][j] == 0) continue;
            if(!v[j]){
                v[j] = true;
                dfs(depth + 1, j, sum + arr[cur][j]);
                v[j] = false;
            }
        }
    }
}


카테고리:

업데이트:

댓글남기기