【AtCoder Regular Contest 064 E】Cosmic Rays

最短路。

题目大意:

给定平面上 $n$ 个圆形区域,要求从一个点走到另一个点,使得暴露在圆形区域外的路径尽可能少。求暴露在圆形区域外的路径的最小值。

题解:

把起点和终点看成半径为 $0$ 的圆形区域我们每次显然是从一个圆形区域,沿最短路走到另一个圆形区域。

两个圆形区域之间的最短路为其圆心距离减去两圆的半径。和 $0$ 取 $\max$。

跑 Dijkstra 即可。时间复杂度 $O(n^2)$。

注意这是一张完全图,所以用堆会更劣。

Code:

#include<cstdio>
#include<cmath>
const int N=1233;
int n,X[N],Y[N],R[N];
double dis[N];
bool vis[N];
inline double Dist(int x,int y){return sqrt(1.*x*x+1.*y*y);}
int main(){
    scanf("%d%d%d%d%d",X+1,Y+1,X+2,Y+2,&n),n+=2;
    for(int i=3;i<=n;++i)scanf("%d%d%d",X+i,Y+i,R+i);
    for(int i=2;i<=n;++i)dis[i]=1e18;
    for(int T=1;T<n;++T){
        int u=0;
        for(int i=1;i<=n;++i)
        if((!u||dis[i]<dis[u])&&!vis[i])u=i;
        vis[u]=1;
        for(int i=1;i<=n;++i)
        if(u!=i&&!vis[i]){
            double nd=Dist(X[u]-X[i],Y[u]-Y[i])-R[u]-R[i];
            if(nd<0)nd=0;
            if(dis[i]>dis[u]+nd)dis[i]=dis[u]+nd;
        }
    }
    printf("%.15f\n",dis[2]+1e-15);
    return 0;
}