-
题面:氏旅行售货员问题是对给定的平面上n 个点确定一条连接这n 个点的长度最短的哈密顿回路。由于欧氏距离满足三角不等式,所以欧氏旅行售货员问题是一个特殊的具有三角不等式性质的旅行售货员问题。它仍是一个NP 完全问题。最短双调TSP 回路是欧氏旅行售货员问题的特殊情况。平面上n 个点的双调TSP 回路是从最左点开始,严格地由左至右直到最右点,然后严格地由右至左直至最左点,且连接每一个点恰好一次的一条闭合回路。
-
数据输入:由文件input.txt 给出输入数据。第1 行有1 个正整数n,表示给定的平面上的点数。接下来的n 行中,每行2 个实数,分别表示点的x 坐标和y 坐标。
-
数据输出: 将计算的最短双调TSP 回路的长度(保留2 位小数)输出到文件output.txt 。
-
样例输入:
70 6
1 0
2 3
5 4
6 1
7 5
8 2
-
样例输出:
25.58 -
代码
/** * 请不要质疑1+1=2 */ #include <iostream> #include <iomanip> #include <algorithm> //sort #include <map> #include <queue> #include <deque> //双端队列,头可插,尾可插 #include <string> #include <cstring> #include <stack> #include <cmath> #include <fstream> #include <ctime> #include <climits> //数值的限制范围 //(double)clock() / CLOCKS_PER_SEC <= 0.95 限制0.95s跑完 using namespace std; class Solver { //通用属性 public: string name; bool isDebug; Solver(const string name, const bool isDebug) { this->name = name; this->isDebug = isDebug; } //通用方法 protected: static int QuickRead() { int num = 0, flag = 1; char ch = getchar(); //读符号 while (ch < '0' || ch > '9') { if (ch == '-') { flag = -1; } ch = getchar(); } //读数值 while (ch >= '0' && ch <= '9') { num = (num << 1) + (num << 3) + (ch ^ 48); ch = getchar(); } return flag * num; } public: void SaveCpp() const { fstream input; fstream output; input.open("moota.cpp", ios::in); const string file = name + ".cpp"; output.open(file.c_str(), ios::out); char c = 'O'; while (!input.eof()) { input.get(c); output << c; } input.close(); output.close(); } void Debug(const string message) const { if (isDebug) { cout << message; } } protected: //待实现方法 virtual void BeginPlay() { Debug("\n---BeginPlay---\n"); }; virtual void Playing() { Debug("\n---Playing---\n"); }; virtual void EndPlay() { Debug("\n---EndPlay---\n"); }; public: //外观模式 void Play() { BeginPlay(); Playing(); EndPlay(); } }; class Player { private: string name; public: Player(const string name) { this->name = name; } void Play(Solver* solver) const { if (solver->isDebug) { cout << "\n" << name << "开始做题\n"; solver->SaveCpp(); } solver->Play(); } }; class SpecialSolver : public Solver { public: static const int MAX = int(1e7); static const long long INF = (long long)1e18; SpecialSolver(const string name, const bool isDebug): Solver(name, isDebug) { } private: //实例属性 int n; struct Node { int x, y; bool operator<(const Node& other) const { return x < other.x; } } node[1000]; double dp[100][100]; double dis[100][100]; private: //实例方法 void Dp() { //dis数组初始化 for (int i = 1; i <= n; ++i) { for (int j = i; j <= n; ++j) { const int gapX = node[i].x - node[j].x; const int gapY = node[i].y - node[j].y; dis[i][j] = sqrt(gapX * gapX + gapY * gapY); } } dp[1][2] = dis[1][2]; for (int j = 3; j <= n; ++j) { for (int i = 1; i < (j - 1); ++i) { dp[i][j] = dp[i][j - 1] + dis[j - 1][j]; } double minValue = MAX; for (int k = 1; k < (j - 1); ++k) { minValue = min(minValue, dp[k][j - 1] + dis[k][j]); } dp[j - 1][j] = minValue; } dp[n][n] = dp[n - 1][n] + dis[n - 1][n]; } protected: virtual void BeginPlay() override { Solver::BeginPlay(); cin >> n; for (int i = 1; i <= n; ++i) { cin >> node[i].x >> node[i].y; } sort(node + 1, node + n + 1); }; virtual void Playing() override { Solver::Playing(); Dp(); }; virtual void EndPlay() override { Solver::EndPlay(); cout << fixed << setprecision(2) << dp[n][n]; }; }; //注意改名字和状态 Player player("moota"); SpecialSolver specialSolver("双调旅行售货员问题", true); int main() { player.Play(&specialSolver); }
数据结构与算法-双调旅行售货员问题
最新推荐文章于 2022-11-09 10:10:39 发布