zoukankan      html  css  js  c++  java
  • 欧涛最短路

    题目链接:https://ac.nowcoder.com/acm/contest/1168/C

    来源:牛客网

    题目描述

    已知了飞行器的起点和终点以及n个休息站的坐标,问起点到终点的最短路径是多少?

    限制:飞行器不能长期飞行,必须中途在某结点下停下休息。(即连续飞行距离应不大于m)

    欧涛师兄很想在师妹面前大展身手,你能帮助他解决这个问题吗?

    输入描述:

    第一行输入两个数,整数n和浮点数m

    第二行输入六个浮点数x1,y1,z1,x2,y2,z2。分别代表起点坐标(x1,y1,z1)和终点坐标(x2,y2,z2)

    紧接着下面n行,每行依次输入三个浮点数,代表休息站的坐标(ai,bi,ci),休息站编码依次为1,2……n。

    输出描述:

    输出满足条件的起点到终点的最短距离长度(结果保留三位小数)。

    依次输出飞行器经过站台的编码(休息站编码为1到n,起点编码Start,终点编码End)

    若不能到达终点输出“-1”(无双引号)
    示例1

    输入

    复制
    4 5
    0 0 0 6 6 0 
    -1 1 0
    5 6 0
    3 4 0 
    6 1 0
    

    输出

    复制
    8.606
    Start 3 End
    

    备注:

    n<=600


    思路:就是朴素版的dijkstra。只不过要存到达终点的路径。纠结半天没出来,归根到底还是对原理不熟悉,这里最关键的就是要记录路径。
    这里用一个path数组,path[j]=k表示到达j必须经过k,每次松弛操作找到更短的边都要更新路径。然后这道题就出来了。这里的path和kmp的next数组有异曲同工之妙。

    #include<stdio.h>
    #include<math.h>
    const int maxn=1e6+10;
    const int inf=0x7fffffff;
    using namespace std;
    
    typedef struct P{
        double x,y,z;
    }Node;
    
    int qq,t,n,cnt,vis[600+10],path[600+10],stack[600+10];
    double m,Chara[600+10][600+10],dis[600+10];
    Node u,v,a[600+10];
    
    void D(int N)
    {
        for(int i=0;i<=N;i++)
        {
            dis[i] = Chara[0][i];
        }
        dis[0] = 0;
        vis[0] = 1;
        for(int i=0;i<=N;i++)
        {
            double ans = inf;
            int k;
            for(int j=0; j<=N; j++)
            {
                if(!vis[j]&&dis[j]<ans)
                {
                    k = j;
                    ans = dis[j];
                }
            }
            vis[k] = 1;
            if(ans==inf)break;
            for(int j=0; j<=N; j++)
            {
                if(!vis[j] &&  dis[k] + Chara[k][j]<dis[j])
                {
                    dis[j] = dis[k] + Chara[k][j];
                    path[j]=k;
                }
            }
        }
    }
    double distance(int x,int y)
    {
        return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y)+(a[x].z-a[y].z)*(a[x].z-a[y].z));
    }
    int main()
    {
        scanf("%d%lf",&n,&m);
        scanf("%lf%lf%lf",&a[0].x,&a[0].y,&a[0].z);
        scanf("%lf%lf%lf",&a[n+1].x,&a[n+1].y,&a[n+1].z);
        for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
        for(int i=0;i<=n+1;i++)
        {
            for(int j=0;j<=n+1;j++)
            {
                double pp=distance(i,j);
                if(pp>m)Chara[i][j]=inf;
                else if(i==j) Chara[i][j]=0;
                else Chara[i][j]=pp;
            }
        }
        D(n+1);
        if(dis[n+1]==inf)printf("-1
    ");
        else
        {
            qq=n+1;
            cnt=1;
            while(path[qq])
            {
                stack[cnt++]=path[qq];
                qq=path[qq];
            }
            printf("%.3lf
    ",dis[n+1]);
            printf("Start");
            for(int i=cnt-1;i>0;i--)printf(" %d",stack[i]);
            printf(" End");
        }
        return 0;
    }
  • 相关阅读:
    Linux基本命令(一)
    Linux基本命令(一)
    前端js实现打印excel表格
    前端js实现打印excel表格
    前端js实现打印excel表格
    前端js实现打印(导出)excel表格
    前端js实现打印(导出)excel表格
    混合开发中拍照和打电话功能的代码
    混合开发中拍照和打电话功能的代码
    操作系统的发展史(科普章节)
  • 原文地址:https://www.cnblogs.com/Mingusu/p/11873171.html
Copyright © 2011-2022 走看看