poj 2677

双调欧几里得旅行商问题:

http://blog.sina.com.cn/s/blog_51cea4040100gkcq.html

f(i,j)表示第一个人走到i点,第二个人走到j点所行走的最短距离,前i个都已经走过。

所以将要到达第i个点时,第i个点有可能交给第一个人,也有可能交给第二个人,两种情况下与f(i-1,j) 都有什么关系呢?

第一种情况下:f(i,j)=min{f(i,j),f(i-1,j)+dist(i-1,i)};

第二种情况下:f(i,i-1)=min{f(i,i-1),f(i-1,j)+dist(j,i)};(f(i,i-1)==f(i-1,i))

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MAX 123456789
struct point
{
double x,y;
};
point vert[101];
double res[101][101];
double dis(int i,int j)
{
return sqrt((vert[i].x-vert[j].x)*(vert[i].x-vert[j].x)+(vert[i].y-vert[j].y)*(vert[i].y-vert[j].y));
}
double min(double a,double b)
{
return a < b ? a : b;
}
double work(int n)
{
int i,j;
double s,Min=MAX;
res[2][1]=dis(2,1);
for(i=2;i<=n;i++)
{
for(j=1;j<i;j++)
{
res[i][j]=min(res[i][j],res[i-1][j]+dis(i-1,i));
res[i][i-1]=min(res[i][i-1],res[i-1][j]+dis(j,i));
}
}
for(i=1;i<n;i++)
{
s=dis(i,n);
if(Min > res[n][i] + s) Min = res[n][i] + s;
//printf("%.2lf\n",res[n][i] + s);
}
return Min;
}
int main()
{
int i,j,n;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%lf %lf",&vert[i].x,&vert[i].y);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) res[i][j]=MAX;

printf("%.2lf\n",work(n));
}
return 0;
}



posted @ 2012-03-20 20:05  书山有路,学海无涯  阅读(611)  评论(0编辑  收藏  举报