题目描述
你是一艘战列巡洋舰的引擎操作人员,这艘船的船员在空间中侦测到了一些无法辨识的异常信号。你的指挥官给你下达了命令,让你制定航线,驾驶战列巡洋舰到达那里。
船上老旧的曲速引擎的速度是0.1AU/s0.1AU/s0.1AU/s。然而,在太空中分布着许多殖民星域,这些星域可以被看成一个球。在星域的内部,你可以在任何地方任意次跳跃到星域内部的任意一个点,不花费任何时间。
你希望算出到达终点的最短时间。
题目解析
把星域,起点,终点看作一个三维空间上的点,并且起点和终点的半径为000。
在任意两个点的之间航行的时间等于两个点之间的距离减去两个点的半径。
将每个点当作点建图,然后运行最短路算法即可。
代码
#include<bits/stdc++.h>
using namespace std;
int n;
double m[105][105],dis[105];
queue<int> q;
bool vis[105];
struct A
{
double x,y,z,r;
}a[105];
double fun(int i,int j)
{
int x=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)+(a[i].z-a[j].z)*(a[i].z-a[j].z);
double k=sqrt(x);
if(k>a[i].r+a[j].r) return k-a[i].r-a[j].r;
else return 0;
}
void spfa()
{
for(int i=0;i<105;i++) dis[i]=1e9;
dis[0]=0;
q.push(0);
while(!q.empty())
{
int x=q.front();q.pop();
vis[x]=0;
for(int i=0;i<=n+1;i++)
if(m[x][i]>=0&&m[x][i]+dis[x]<dis[i])
{
dis[i]=dis[x]+m[x][i];
if(!vis[i])
{
q.push(i);
vis[i]=1;
}
}
}
}
int main()
{
freopen("warp.in","r",stdin);
freopen("warp.out","w",stdout);
cin>>n;
while(n!=-1)
{
memset(m,0,sizeof(m));
memset(a,0,sizeof(a));
for(int i=2;i<=n+1;i++)
cin>>a[i].x>>a[i].y>>a[i].z>>a[i].r;
cin>>a[0].x>>a[0].y>>a[0].z;a[0].r=0;
cin>>a[1].x>>a[1].y>>a[1].z;a[1].r=0;
for(int i=0;i<=n+1;i++)
for(int j=i;j<=n+1;j++)
if(i==j)
m[i][j]=-1;
else
m[i][j]=m[j][i]=fun(i,j);
spfa();
cout<<round(dis[1]*10)<<endl;
cin>>n;
}
}