Cosmic Rays(dijsktra)

6487: Cosmic Rays

时间限制: 1 Sec  内存限制: 128 MB

题目描述

On the xy-plane, Snuke is going to travel from the point (xs,ys) to the point (xt,yt). He can move in arbitrary directions with speed 1. Here, we will consider him as a point without size.
There are N circular barriers deployed on the plane. The center and the radius of the i-th barrier are (xi,yi) and ri, respectively. The barriers may overlap or contain each other.
A point on the plane is exposed to cosmic rays if the point is not within any of the barriers.
Snuke wants to avoid exposure to cosmic rays as much as possible during the travel. Find the minimum possible duration of time he is exposed to cosmic rays during the travel.

Constraints
All input values are integers.
−109≤xs,ys,xt,yt≤109
(xs,ys) ≠ (xt,yt)
1≤N≤1,000
−109≤xi,yi≤109
1≤ri≤109

输入

The input is given from Standard Input in the following format:
xs ys xt yt
N
x1 y1 r1
x2 y2 r2
:
xN yN rN

输出

Print the minimum possible duration of time Snuke is exposed to cosmic rays during the travel. (精确到小数点后9位)

样例输入

-2 -2 2 2
1
0 0 1

样例输出

3.656854249

提示

An optimal route is as follows:

 

 

来源

ABC048&ARC064 

 

自己是看不出来的,又是英文又是好久没敲的最短路

 

题意   :

            给你n个圆,s,t两个点,要求从s走到t,尽可能的让路线被圆包含,

然后求最短的不被包含的长度。。

思路  :

            将圆看成点,就是从s到t点共n+2个点 的最短路问题,其中每两个点的

距离为,圆心距减去两圆的半径(如果大于等于0的话,否则为零,即大圆套小圆)

然后走一个dijsktra,完毕#

 

代码————洛谷上好像过不去,改成long double 会多过几个实例

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;

double arr[1024][1024],tp[1024];
int vis[1024];
int n;
struct p
{
    int x,y,r;
}q[1024];
void dij()
{
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    for(int i=1;i<=n;i++)
        tp[i]=arr[1][i];

    int f=0;

    for(int i=2;i<=n;i++)
    {
        int indx=0;
        double minn=inf;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j] && minn>tp[j])
            {
                minn=tp[j];
                indx=j;
            }
        }
        if(!indx)
        {
            f=1;
            break;
        }
        vis[indx]=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j] && tp[j]>arr[indx][j]+tp[indx])
                tp[j]=arr[indx][j]+tp[indx];
        }
    }
}

double F(int i,int j)
{
    return sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y))-q[i].r-q[j].r;
}

int main(){

    scanf("%d%d%d%d",&q[1].x,&q[1].y,&q[2].x,&q[2].y);
    q[2].r=q[1].r=0;
    scanf("%d",&n);

    for(int i=3;i<=n+2;i++)
    {
        scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].r);
    }
    n=n+2;


    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            arr[i][j]=arr[j][i]=max(0.,F(i,j));
        }
    }

    dij();

    printf("%.9lf\n",tp[2]);

    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值