hdu 2224 The shortest path

来源:互联网 发布:js div旋转动画 编辑:程序博客网 时间:2024/06/09 23:11

本题归结为旅行推销员问题(Travelling Salesman Problem, 又称为旅行商问题、货郎担问题、TSP问题)是一个多局部最优的最优化问题:有n个城市,一个推销员要从其中某一个城市出发,唯一走遍所有的城市,再回到他出发的城市,求最短的路线。

研究NP问题时看到了计算欧式平面最短哈密顿回路的贪心算法, 只能得到近似解

此算法在本题上得到了应用

具体求解步骤为将计算简化为求出最短双调TSP回路, 将所有点按x坐标排序后, 先从最左端点向右走按递增顺序达到最右端点然后再按递减顺序走回, 因为期间没有折返, 所以可以保证x方向局部最优.

由于题目给出的点已经按x坐标排序, 所以可以省去排序这一步

这种贪心算法的优势在于时间效率, 如果要得到最优解, 需要枚举每两个点, 算法复杂度将达到O(n!). 如果利用动态规划则可以达到O(n^2 2^n) 但仍然太慢

利用双调TSP回路计算, 在应用动归时算法复杂度只有O(n^{2})


对于其他的TSP求解方法可以参见:

http://episte.math.ntu.edu.tw/articles/mm/mm_11_3_02/index.html

具体算法图示可见http://en.wikipedia.org/wiki/Travelling_salesman_problem



/*author: birdstorm*/#include <iostream>#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <climits>#define MAXN 205#define N 105#define inf 1.0e20#define eps 1.0e-10#define MOD 1000000007#define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL long longusing namespace std;pair<int,int> p[MAXN];double dp[MAXN][MAXN], dist[MAXN][MAXN];double dis(int x, int y){    double t1=p[x].first-p[y].first;    double t2=p[x].second-p[y].second;    return sqrt(t1*t1+t2*t2);}int main(){    int n;    while(~scanf("%d",&n)){        double ans=inf;        rep(i,1,n) scanf("%d%d",&p[i].first,&p[i].second);        rep(i,2,n) rep(j,1,i-1) dist[i][j]=dis(i,j);        dp[2][1]=dist[2][1];        rep(i,3,n){            rep(j,1,i-2) dp[i][j]=dp[i-1][j]+dist[i][i-1];            dp[i][i-1]=inf;            rep(j,1,i-2) dp[i][i-1]=min(dp[i-1][j]+dist[i][j],dp[i][i-1]);            if(i==n) dp[i][i]=dp[i][i-1]+dist[i][i-1];        }        printf("%.2lf\n",dp[n][n]);    }    return 0;}


0 0