GMOJ P3517 【空间航行】

Description

给你起点和终点的三维坐标 $(s_x,s_y,s_z)$ 和 $(e_x,e_y,e_z)$ ,以及 $n$ 个球的球心的三维坐标 $(x_i,y_i,z_i)$ 和星域的半径 $r_i$ 。现在要从起点到终点,在一个球内穿梭不需要时间,你的速度是 $0.1$ ,现在请你求出从起点到终点所需的最短时间,结果取整到最近的整数,输入数据保证取整是明确的。

$0 \leq n \leq 100,0 \leq |x_i|,|y_i|,|z_i|,r_i\leq 10^4$ 。

Solution

考虑使用 Floyd 来解题。

把起点和终点也当做一个半径为 的球来存,然后给任意两点之间先建一条边。

考虑两个球之间的最短路,可以得出为两个圆心之间的距离减去两个球的半径,即:

$\sqrt{(z_i-z_j)^2+(x_i-x_j)^2+(y_i-y_j)^2}-r_i-r_j$。

然后就很舒服了,直接套一个 Floyd 即可。

时间复杂度 O(n^3) ,具体细节详见 代码 部分。

然后这道题目就做完了。

Code

1
#include<map>
2
#include<queue>
3
#include<cmath>
4
#include<cstdio>
5
#include<vector>
6
#include<string>
7
#include<cstring>
8
#include<iostream>
9
#include<algorithm>
10
using namespace std;
11
int n,x[101],y[101],z[101],r[101],t;
12
double sx,sy,sz,ex,ey,ez;
13
double nx,ny,nz,dx,dy,dz;
14
double ma[103][103];
15
double abss(double x){return x>(-x)?x:(-x);}
16
double minn(double x,double y){return x<y?x:y;}
17
int main()
18
{
19
    freopen("warp.in","r",stdin);
20
    freopen("warp.out","w",stdout);
21
    cin>>n;
22
    while(n!=-1)
23
    {
24
        for(int i=1;i<=n;i++)
25
            cin>>x[i]>>y[i]>>z[i]>>r[i];
26
        cin>>sx>>sy>>sz>>ex>>ey>>ez;
27
        x[++n]=sx;y[n]=sy;z[n]=sz;r[n]=0;
28
        x[++n]=ex;y[n]=ey;z[n]=ez;r[n]=0;
29
        for(int i=1;i<=n;i++)
30
        {
31
            for(int j=i+1;j<=n;j++)
32
            {
33
                ma[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
34
                ma[i][j]=ma[j][i]=sqrt(ma[i][j]*ma[i][j]+(z[i]-z[j])*(z[i]-z[j]))-r[i]-r[j];
35
                if(ma[i][j]<0)
36
                {
37
                    ma[i][j]=ma[j][i]=0;
38
                }
39
            }
40
        }
41
        for(int k=1;k<=n;k++)
42
        {
43
            for(int i=1;i<=n;i++)
44
            {
45
                for(int j=1;j<=n;j++)
46
                {
47
                    if(i!=j&&j!=k&&i!=k)
48
                    {
49
                        ma[i][j]=minn(ma[i][j],ma[i][k]+ma[k][j]);
50
                    }
51
                }
52
            }
53
        }
54
        printf("%.0lf\n",ma[n-1][n]*10.00);
55
        cin>>n;
56
    }
57
    return 0;
58
}