Problem Description
在数码世界的某次战争中,年轻的狮子兽收到了一封密函,密函中指出需要让他从当前坐标赶往另一个坐标去狙击敌人的精英部队。但是狮子兽知道,整个战场都有可能被敌方的飞行兽从上往下侦查到,因此需要注意隐匿自己的行踪。
狮子兽虽然年轻,但他对战场非常了解,他知道在战场上存在N个无法被飞行兽侦查到的浮空圆盘,只要在浮空圆盘内部(包括圆盘边界,下同)就不会被飞行兽侦查到(浮空圆盘可能重叠)。
现在狮子兽想要从当前坐标前往指定坐标(假设其行进速度恒定,1单位时间行进1单位距离),但是为了减少暴露自己的可能,所以想使不在浮空圆盘内部的时间尽可能少。
注意:整个战场是一个连续二维坐标平面,地势平缓,且狮子兽的行进可以是任何方向、可以是直线也可以是曲线。
Input
每个输入文件中一组数据。
第一行一个正整数N(1<=N<=1000),表示浮空圆盘的个数。
接下来N行,每行三个整数x, y, r(-1000<=x,y<=1000、0<=r<=10),分别代表浮空圆盘的坐标(x,y)和半径r。
最后分两行给出狮子兽的当前坐标和目的坐标,每行两个整数x, y(-1000<=x,y<=1000)。
Output
输出不在浮空圆盘内部的最少时间(即不得不暴露在飞行兽侦查下的最少时间)。结果精度保留两位小数。
Sample Input
1
0 0 1
2 0
0 2
Sample Output
2.00
Author
Shoutmon
Source
17浙大考研机试模拟赛
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const double inf=9999999999;
struct point
{
int x,y,r;
};
int n;
double A[1024][1024];
vector<point> v;
double sqe(int x)
{
return 1.0*x*x;
}
double getDistance(int i,int j)
{
return max(0.0,sqrt(sqe(v[i].x-v[j].x)+sqe(v[i].y-v[j].y))-v[i].r-v[j].r);
}
double dijkstra(int s,int e)
{
vector<double> dist(A[s],A[s]+n);
vector<bool> visit(n,0);
for(int i=0;i<n;++i)
{
double minval=inf;
int u=-1;
for(int j=0;j<n;++j)
if(minval>dist[j]&&visit[j]==0) minval=dist[u=j];
visit[u]=1;
for(int w=0;w<n;++w)
{
if(visit[w]) continue;
if(dist[w]>dist[u]+A[u][w])
dist[w]=dist[u]+A[u][w];
}
}
return dist[e];
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
{
point p;
scanf("%d %d %d",&p.x,&p.y,&p.r);
v.push_back(p);
}
point s,e;
scanf("%d %d",&s.x,&s.y);
scanf("%d %d",&e.x,&e.y);
s.r=e.r=0;
v.push_back(s);
v.push_back(e);
n=v.size();
for(int i=0;i<n;++i)
{
for(int j=0;j<i;++j)
A[i][j]=A[j][i]=getDistance(i,j);
A[i][i]=0.0;
}
double ans=dijkstra(n-2,n-1);
printf("%.2lf\n",ans);
return 0;
}