1 분 소요

문제

외판원 순회 문제는 영어로 Traveling Salesman problem (TSP) 라고 불리는 문제로 computer science 분야에서 가장 중요하게 취급되는 문제 중 하나이다.
도시가 N개 있고, 각 도시들 사이에는 길이 있을 수도, 없을 수도 있다. 이제 한 외판원이 한 도시에서 출발해 N개의 도시를 모두 거쳐 다시 원래의 도시로 돌아오는 순회 여행 경로를 계획하려고 한다.
단, 한 번 갔던 도시로는 다시 갈 수 없다. (맨 마지막에 여행을 출발했던 도시로 돌아오는 것은 예외)
이런 여행 경로 중에서 가장 적은 비용을 들이는 여행 계획을 세우고자 한다.

입력

첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 16)
다음 N개의 줄에는 비용 행렬이 주어진다.
각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다.
W[i][j]는 도시 i에서 j로 가기 위한 비용을 나타낸다.
항상 W[i][i] = 0이다.

예제 입력 1

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

출력

첫째 줄에 외판원의 순회에 필요한 최소 비용을 출력한다.

예제 출력 1

35

풀이

문제 해결 방법

이 문제는 TSP(Traveling Salesman Problem)의 대표적인 예시로, 다이나믹 프로그래밍과 비트마스킹을 함께 사용하여 해결할 수 있습니다. 주요 해결 단계는 다음과 같습니다:

  1. 상태 표현: 현재 방문한 도시들의 집합과 현재 위치를 상태로 표현
  2. 비트마스킹: 방문한 도시들의 집합을 비트마스크로 표현
  3. DP 테이블: dp[방문한 도시들의 상태][현재 위치]
  4. 최적해 계산: 모든 도시를 방문한 후 출발 도시로 돌아오는 최소 비용 계산

이 알고리즘의 시간 복잡도는 O(N² × 2^N)입니다.

코드

#include<stdio.h>
#include<algorithm>

using namespace std;

int dp[66000][17];
int n;
int mp[17][17];

int main()
{
    int i, j, k;

    scanf("%d", &n);
    for (i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            scanf("%d", &mp[i][j]);

    for (i = 0; i <= (1 << n); i++)
    {
        for (j = 1; j <= n; j++)
            dp[i][j] = 1e9;
    }

    dp[1][1] = 0;

    for (i = 2; i < (1 << n); i++)
    {
        for (j = 1; j <= n; j++)
        {
            if (i &(1 << (j - 1)))
            {
                int v = i - (1 << (j - 1));
                for (k = 1; k <= n; k++)
                {
                    if (mp[k][j] == 0)continue;
                    dp[i][j] = min(dp[i][j], dp[v][k] + mp[k][j]);
                }
            }
        }
    }

    int mn = 1e9;
    int v = (1 << n) - 1;
    for (i = 2; i <= n; i++)
    {
        if (mp[i][1] == 0)continue;
        mn = min(mn, dp[v][i] + mp[i][1]);
    }

    printf("%d", mn);

    return 0;
}

댓글남기기