给定一张 nn 个点的带权无向图,点从 0∼n−10∼n−1 标号,求起点 00 到终点 n−1n−1 的最短 Hamilton 路径。
Hamilton 路径的定义是从 00 到 n−1n−1 不重不漏地经过每个点恰好一次。
输入格式
第一行输入整数 nn。
接下来 nn 行每行 nn 个整数,其中第 ii 行第 jj 个整数表示点 ii 到 jj 的距离(记为 a[i,j]a[i,j])。
对于任意的 x,y,zx,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x]a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]≥a[x,z]a[x,y]+a[y,z]≥a[x,z]。
输出格式
输出一个整数,表示最短 Hamilton 路径的长度。
数据范围
1≤n≤201≤n≤20
0≤a[i,j]≤107
- #include
- #include
- #include
-
- using namespace std;
-
- const int N = 20, M = 1 << N;
-
- int n;
- int w[N][N];
- int f[M][N];//f[i][j]表示当前状态为i时,停在j点
-
- int main()
- {
- cin >> n;
- for (int i = 0; i < n; i ++ )
- for (int j = 0; j < n; j ++ )
- cin >> w[i][j];
-
- memset(f, 0x3f, sizeof f);
- f[1][0] = 0;
-
- for (int i = 0; i < 1 << n; i ++ )
- for (int j = 0; j < n; j ++ )
- if (i >> j & 1)
- for (int k = 0; k < n; k ++ )
- if (i >> k & 1)//i状态必须包括k,换句话说i的第k位必须是1
- f[i][j] = min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
-
- cout << f[(1 << n) - 1][n - 1];
-
- return 0;
- }