Tour UVA - 1347 双调欧几里得旅行商问题(dp)

思路

按照紫书的算法思路:考虑两个人同时从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;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/82793709