1 条题解

  • 0
    @ 2025-8-24 21:26:03

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 封禁用户
    None

    搬运于2025-08-24 21:26:03,当前版本为作者最后更新于2016-12-20 21:21:54,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    先上代码

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int mm=1111;
    struct data
    {
        double x,y;
    }g[mm];
    double d[mm][mm],f[mm][mm];
    int i,j,k,n;
    bool cmp(const data &a,const data &b)
    {
        return a.x<b.x;
    }
    double mdis(const data &a, const data &b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    int main()
    {
        scanf("%d",&n);
        for(i=0;i<n;++i)
            scanf("%lf%lf",&g[i].x,&g[i].y);
        sort(g,g+n,cmp);
        for(i=0;i<n;++i)
            for(j=i+1;j<n;++j)
            {
                d[i][j]=mdis(g[i],g[j]);
                f[i][j]=1e30;
            }
        f[0][1]=d[0][1];
        for(i=0;i<n;++i)
            for(j=i+1;j<n;++j)
            {
                f[i][j+1]=min(f[i][j+1],f[i][j]+d[j][j+1]);
                f[j][j+1]=min(f[j][j+1],f[i][j]+d[i][j+1]);
            }
        double ans=1e30;
        for(j=0;j<n-1;++j)
            ans=min(ans,f[j][n-1]+d[j][n-1]);
        printf("%.2lf\n",ans);
        return 0;
    }
    

    【1】题意:旅行商问题,不过要求只能单向走,就是有n个地方,要求从西往东,到最东面的地方,在从东往西返回,经过每个点一次,求最短路径

    【2】分析:由于有了方向的限制,这题不再是NP难题,我们可以假设有两个人一起从西往东走,走过的点不能重复,这样就有f[ i ][ j ]表示第一个人走到i,第二个人走到j 的最短路径,要求i<j,且0到j的点都被经过了,这样很容易想到,j+1的点不是被第一个人走,就是被第二个人走,所以有转移方程f[ i ][ j+1]=min{ f[ i ] [ j ]+d[ j ] [ j +1] } f[ j ] [ j+1 ]=min{ f[ i ][ j ]+d[ i ][ j+1 ] },第一个转移方程很容易理解,第二个方程可以这么理解,两个人可以指前面一个人,和后面一个人,当后面的人走到前面,当然就对换过来了,不影响结果

    【3】最后,预处理f[ 0 ][ 1]还有扫描 一遍答案就行了,这题算是一类DP吧,思路挺有启发性的

    ###Built by SinGuLaRiTy

    • 1

    信息

    ID
    516
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者