题目
(目前比较流行的说法是叫旅行商问题)
思路
直接规定起点和终点都是城市0。(原因慢慢想)
1.状态定义:d(i,S),当前处于i城市,还需访问S中的城市各一次最后回到城市0的最短长度。
2.边界:d(i,{}) = dist(0,i)
3.答案:d(0, {1,2,3,…,n-1})
4.状态转移方程:
d(i,S)=min{d(j,S−{j}+dist(i,j)|j∈S}
d
(
i
,
S
)
=
m
i
n
{
d
(
j
,
S
−
{
j
}
+
d
i
s
t
(
i
,
j
)
|
j
∈
S
}
5.时间复杂度: O(n22n) O ( n 2 2 n ) (理论上)
代码
(代码没有进行过测试)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int maxn = 15 + 1;
const int maxsum = 1 << 16;
const int INF = 1 << 20;
int n, G[maxn][maxn], d[maxn][maxsum];
void dp(int i, int S) {
if (S == 0) {
d[i][S] = G[0][i];
return;
}
d[i][S] = INF;
_for(j, 0, n)
if (S & (1 << j))
d[i][S] = min(d[i][S], d[j][S ^ (1 << j)] + G[i][j]);
}
int main() {
scanf("%d", &n);
_for(i, 0, n) // 理想输入
_for(j, 0, n)
scanf("%d", &G[i][j]);
dp(0, (1 << n) - 1);
printf("%d\n", d[0][(1 << n) - 1 - 1]);
return 0;
}