1 #include <algorithm>
2 #include <cmath>
3 #include <cstdio>
4 #include <cstring>
5 #include <deque>
6 #include <iostream>
7 #include <map>
8 #include <queue>
9 #include <set>
10 #include <stack>
11 #include <string>
12 #include <vector>
13 using namespace std;
14 typedef long long LL;
15 const int maxn = 18;
16 const double PI = acos(-1);
17 const int mod = 1e9 + 7;
18 using namespace std;
19 // 定义常量
20 const int INF = 0x3f3f3f3f;
21 #define sqr(x) ((x) * (x))
22 // 定义变量
23 int type; // type == 1 满秩矩阵格式, type == 2 二维坐标式
24 int s;
25 int N; // 城市结点数量
26 int init_point;
27 double dp[1 << maxn][maxn];
28 // 动态规划状态数组dp[i][j],i表示集合V’,j表示当前到达的城市结点
29 double dis[maxn][maxn]; // 两个城市结点之间的距离
30 vector<int> path[1 << maxn][maxn];
31 double ans;
32 vector<int> ans_path;
33 // 定义结构体
34 struct vertex {
35 double x, y; // 城市结点的坐标
36 string id; // 城市结点的id
37 void input() {
38 cin >> id;
39 scanf("%lf %lf", &x, &y);
40 }
41 } node[maxn];
42
43 double Dist(const vertex &a, const vertex &b) {
44 return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
45 }
46
47 void init() { // 数据初始化
48 scanf("%d", &N);
49 for (int i = 0; i < N; i++)
50 node[i].input();
51 for (int i = 0; i < N; i++) {
52 for (int j = 0; j < N; j++)
53 dis[i][j] = Dist(node[i], node[j]); // 计算城市之间的距离
54 }
55 for (int i = 0; i < (1 << N); i++) {
56 for (int j = 0; j < N; j++)
57 dp[i][j] = INF,path[i][j].clear();
58 } // 初始化,除了dp[1][0],其余值都为INF
59 ans = INF;
60 return;
61 }
62 //复杂度 2^N * N^2
63 void slove() {
64 int M = (1 << N);
65 // M就是第四部分所说的V’状态总数,1<<N表示2^N,总共有2^N种状态
66 dp[1][0] = 0;
67 path[1][0].push_back(0);
68 // 假设固定出发点为0,从0出发回到0的花费为0。TSP只要求是一个环路,所以出发点可以任选
69 for (int i = 1; i < M; i++) {
70 // 枚举V’的所有状态
71 for (int j = 1; j < N; j++) {
72 // 选择下一个加入集合的城市
73 if (i & (1 << j))
74 continue;
75 // 城市已经存在于V’之中
76 if (!(i & 1))
77 continue;
78 // 出发城市固定为0号城市
79 for (int k = 0; k < N; k++) {
80 // 在V’这个城市集合中尝试每一个结点,并求出最优解
81 if (i & (1 << k)) {
82 // 确保k已经在集合之中并且是上一步转移过来的结点
83 if(dp[i][k] + dis[k][j] < dp[(1 << j) | i][j]){
84 dp[(1 << j) | i][j] = dp[i][k] + dis[k][j];
85 path[(1 << j) | i][j] = path[i][k];
86 path[(1 << j) | i][j].push_back(j);
87 }
88 dp[(1 << j) | i][j] = min(dp[(1 << j) | i][j],
89 dp[i][k] + dis[k][j]); // 转移方程
90 } // 将j点加入到i集合中
91 }
92 }
93 }
94 for (int i = 0; i < N; i++){
95 if(dp[M - 1][i] + dis[i][0]< ans){
96 ans=dp[M - 1][i] + dis[i][0];
97 ans_path = path[M-1][i];
98 }
99 }
100 // 因为固定了出发点,所以要加上到城市0的距离。另外要从所有的完成整个环路的集合V’中选择,完成最后的转移
101 }
102 int main() {
103 #ifndef ONLINE_JUDGE
104 freopen("in.txt", "r", stdin);
105 #endif
106 init();
107 slove();
108 cout<<"TSP路径长度: "<<ans<<endl<<"TSP回路: ";
109 for(int i=0;i<ans_path.size();i++){
110 if(i)cout<<' ';
111 cout<<node[ans_path[i]].id;
112 }cout<<endl;
113 return 0;
114 }