Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3585 | Accepted: 1597 |
Description
Write a program that, given a set of n points in the plane, computes the shortest closed tour that connects the points according to John's strategy.
Input
Output
Sample Input
3 1 1 2 3 3 1 4 1 1 2 3 3 1 4 2
Sample Output
6.47 7.89
Source
转载于:http://blog.sina.com.cn/s/blog_51cea4040100gkcq.html
欧几里得旅行商问题是对平面上给定的n个点确定一条连接各点的最短闭合旅程的问题。如图(a)给出了一个7个点问题的解。这个问题的一般形式是NP完全的,故其解需要多于多项式的时间。
总结一下这种题目解题步骤:
1. 明确所有的点
2. 求出任意两点之间的距离,可以写一个单独的函数,随时调用,也可以预处理,这个“距离”根据题目的不同有不同的意思.
3. 对这些点按x坐标从小到大进行排序
4. 使用双调欧几里得旅行商问题的算法
代码:
#include <iostream>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <string.h>
using namespace std;
const int inf=0x7fffffff;
const int maxn=1000;
int n;//n个点
double dp[maxn][maxn];
struct P
{
double x,y;
}point[maxn];
bool cmp(P a,P b)
{
if(a.x<b.x)
return true;
return false;
}
double dis(P a,P b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double DP(int n)//双调欧几里得旅行商问题算法,dp[n][n]为所求
{
sort(point+1,point+1+n,cmp);
dp[1][2]=dis(point[1],point[2]);
for(int j=3;j<=n;j++)
{
for(int i=1;i<=j-2;i++)
dp[i][j]=dp[i][j-1]+dis(point[j-1],point[j]);
dp[j-1][j]=inf;
for(int k=1;k<=j-2;k++)
{
double temp=dp[k][j-1]+dis(point[k],point[j]);
if(temp<dp[j-1][j])
dp[j-1][j]=temp;
}
}
dp[n][n]=dp[n-1][n]+dis(point[n-1],point[n]);
return dp[n][n];
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>point[i].x>>point[i].y;
cout<<setiosflags(ios::fixed)<<setprecision(2)<<DP(n)<<endl;
}
return 0;
}