欧氏旅行售货员问题是对给定的平面上n 个点确定一条连接这n 个点的长度最短的哈密顿回路。由于欧氏距离满足三角不等式,所以欧氏旅行售货员问题是一个特殊的具有三角不等式性质的旅行售货员问题。它仍是一个NP 完全问题。最短双调TSP 回路是欧氏旅行售货员问题的特殊情况。平面上n 个点的双调TSP 回路是从最左点开始,严格地由左至右直到最右点,然后严格地由右至左直至最左点,且连接每一个点恰好一次的一条闭合回路。
编程任务:
给定平面上n 个点,编程计算这n 个点的最短双调TSP 回路。
数据输入:
由文件input.txt 给出输入数据。第1 行有1 个正整数n,表示给定的平面上的点数。接下来的n 行中,每行2 个实数,分别表示点的x 坐标和y 坐标。
结果输出:
将计算的最短双调TSP 回路的长度(保留2 位小数)输出到文件output.txt 。
输入文件示例
input.txt
7
0 6
1 0
2 3
5 4
6 1
7 5
8 2
输出文件示例
output.txt
25.58
首先对点按x坐标排序
设 d i s [ i ] [ j ] dis[i][j] dis[i][j]的含义为从第i个点走到最左点,再从最左点走到第j个点的最短双调路径,从只有两个点的情形开始推,则初始化 d i s [ 1 ] [ 2 ] = d i s t ( p [ 1 ] , p [ 2 ] ) dis[1][2]=dist(p[1],p[2]) dis[1][2]=dist(p[1],p[2])
对于每个新加入的点j:
#include
#include
#include
#include
using namespace std;
const double inf = 10086;
double dis[51][51];
int n;
struct Point {
double x, y;
bool operator<(const Point& p) {
return x < p.x || (x == p.x && y < p.y);
}
bool operator>(const Point& p) {
return x > p.x || (x == p.x && y > p.y);
}
}p[51];
void qsort(int l, int r) {
if (l < r) {
int i = l, j = r;
Point mid = p[l + (r - l) / 2];
while (i <= j) {
while (p[i] < mid)
i++;
while (p[j] > mid)
j--;
if (i <= j) {
Point t = p[i]; p[i] = p[j], p[j] = t;
i++, j--;
}
}
qsort(l, j);
qsort(i, r);
}
}
double dist(const Point& a, const Point& b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> p[i].x >> p[i].y;
}
qsort(1, n);
dis[1][2] = dist(p[1], p[2]);
for (int j = 3; j <= n; j++) {
for (int i = 1; i <= j - 2; ++i) {
dis[i][j] = dis[i][j - 1] + dist(p[j - 1], p[j]);
}
dis[j - 1][j] = inf;
for (int k = 1; k <= j - 2; ++k) {
double tmp = dis[k][j - 1] + dist(p[k], p[j]);
dis[j - 1][j] = min(tmp, dis[j - 1][j]);
}
}
dis[n][n] = dis[n - 1][n] + dist(p[n - 1], p[n]);
cout << fixed << setprecision(2) << dis[n][n];
return 0;
}