思路
按照紫书的算法思路:考虑两个人同时从1点出发,走不同的路,到达n点。 当一个人走到n-1点的时候,最后还需要走的路径是显然的,因为已经按x轴排好序,所以还要走的最小路径必然是dist(n-1,n)+dist(j,n) :j表示当第一个人走到n-1时,第二个人走到了j点,那么边界条件就被确定了。 下面考虑递推:dp[i][j]表示第一个人在i点,第二个人在j点时,还需走的最小路程。 那么dp[i][j]=min(dp[i+1][j]+dist(i,i+1),dp[i+1][i]+dist(i+1,j), 表示到达i+1点可以有两种走法,要么i点到i+1,要么j点到i+1。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+9;
int n;
double dp[1005][1005];
struct Point
{
double x,y;
}p[maxn];
double dist(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(scanf("%d",&n)!=EOF)
{
memset(dp,127,sizeof(dp));
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
for(int j=1;j<n-1;j++)
{
dp[n-1][j]=dp[j][n-1]=dist(p[n],p[n-1])+dist(p[j],p[n]);
}
for(int i=n-2;i>=1;i--)
{
for(int j=i-1;j>=1;j--)
{
dp[i][j]=dp[j][i]=min(dp[i+1][j]+dist(p[i+1],p[i]),dp[i+1][i]+dist(p[j],p[i+1]));
}
}
printf("%.2lf\n",dp[1][2]+dist(p[1],p[2]));
}
return 0;
}