一、参考文献

前置知识(动态规划入门):《挑战程序设计竞赛》P51 - P69

基础知识(集合整数表示):《挑战程序设计竞赛》P156 - P158

算法详解(状态压缩的DP):《挑战程序设计竞赛》P191 - P193

二、基于递归实现(易于理解)

#include <iostream>
#include <string.h>
using namespace std;
const int MAX_N = 20;
const int INF = 1000000;
int d[MAX_N][MAX_N];
int dp[1 << MAX_N][MAX_N];
int n;
int rec(int S, int v)
{
    if (dp[S][v] >= 0)
    {
        return dp[S][v];
    }
    if (S == (1 << n) - 1 && v == 0)
    {
        return dp[S][v] = 0;
    }
    int res = INF;
    for (int u = 0; u < n; u++)
    {
        if (!(S >> u & 1))
        {
            res = min(res, rec(S | 1 << u, u) + d[v][u]);
        }
    }
    return dp[S][v] = res;
}
void solve()
{
    memset(dp, -1, sizeof(dp));
    printf("%d\n", rec(0, 0));
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &d[i][j]);
        }
    }
    solve();
    return 0;
}

三、基于循环实现(循环速度快)

#include <iostream>
using namespace std;
const int MAX_N = 20;
const int INF = 1000000;
int n;
int d[MAX_N][MAX_N];
int dp[1 << MAX_N][MAX_N];
void solve()
{
    for (int S = 0; S < (1 << n); S++)
    {
        fill(dp[S], dp[S] + n, INF);
    }
    dp[(1 << n) - 1][0] = 0;
    for (int S = (1 << n) - 2; S >= 0; S--)
    {
        for (int v = 0; v < n; v++)
        {
            for (int u = 0; u < n; u++)
            {
                if (!(S >> u & 1))
                {
                    dp[S][v] = min(dp[S][v], dp[S | 1 << u][u] + d[v][u]);
                }
            }
        }
    }
    printf("%d\n", dp[0][0]);
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &d[i][j]);
        }
    }
    solve();
    return 0;
}