一、参考文献
前置知识(动态规划入门):《挑战程序设计竞赛》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;
}