隐匿行踪

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值