双调欧几里得旅行商问题(TSP)

落爺英雄遲暮 提交于 2020-05-07 03:01:50

最小环+欧拉回路=最短哈密顿图

介绍

TSP(Traveling Salesman Problem)即旅行商问题,是数学领域中著名问题之一。这个问题是这样的:假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径长度为所有路径之中的最小值。TSP是一个典型的组合优化问题,且是一个NP完全难题,关于NP的这个概念本文就不做详细介绍了,但简单的说就是:TSP问题目前尚不能找到一个多项式时间复杂度的算法来求解。

n个城市 第一次选择n-1个城市,第二次n-2... 即要遍历n!次,普通遍历复杂度太高

算法

所以TSP旅行商问题有以下4种算法

  • 贪心算法
  • 模拟退火算法
  • 遗传算法
  • 基本蚁群算法

https://blog.csdn.net/wordsin/article/details/79915328

双调欧几里得旅行商问题

这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。事实上,存在确定的最优双调路线的O(n*n)时间的算法。

是对平面上给定的n个点确定一条连接各点的最短闭合旅程的问题。 题目描述 现在笛卡尔平面上有n(n<=1000)个点,每个点的坐标为(x,y)(-2^31<x,y<2^31,且为整数),任意两点之间相互到达的代价为这两点的欧几里德距离 输入格式 第一行一个整数n 接下来n行,每行两个整数x,y,表示某个点的坐标。 输入中保证没有重复的两点, 保证最西端和最东端都只有一个点。 输出格式 一行,即最短回路的长度,保留2位小数。

思路

(1)首先将各点按照x坐标从小到大排列,时间复杂度为O(nlgn)。 (2)寻找子结构:定义从Pi到Pj的路径为:从Pi开始,从右到左一直到P1,然后从左到右一直到Pj。在这个路径上,会经过P1到Pmax(i,j)之间的所有点且只经过一次。

模板

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define INF 1e30 //数据上限
using namespace std;
const int MAX = 1000;//点的最大数
int n;double dis[MAX][MAX],dp[MAX][MAX];
struct node{
    double x,y;
}a[MAX];
bool cmp(node a,node b) {
    return a.x < b.x;
}
double Euc(node a,node b){//计算欧几里得距离
    return sqrt(pow(a.x - b.x,2) + pow(a.y - b.y,2));
}
double DP(){
    sort(a,a + n,cmp);//排序
    for(int i = 0;i < n;i++){
        for(int j = i + 1;j < n;j++){
            dis[i][j] = Euc(a[i],a[j]);
            dp[i][j] = INF;
        }
    }
    dp[0][1] = dis[0][1];
    for(int i = 0;i < n;i++){
        for(int j = i + 1;j < n;j++){
            dp[i][j + 1] = min(dp[i][j + 1],dp[i][j] + dis[j][j + 1]);

            dp[j][j + 1] = min(dp[j][j + 1],dp[i][j] + dis[i][j + 1]);
        }
    }
    double ans=INF;
    for(int i = 0;i < n - 1;i++) ans = min(ans,dp[i][n - 1] + dis[i][n - 1]);
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i = 0;i < n;i++)
        scanf("%lf%lf",&a[i].x,&a[i].y);

    double ans=DP();

    printf("%0.2lf\n",ans);
    return 0;
}

例题

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!