BOJ1509 海边 dijstra 最短路

题意:这题题目写得够坑的。前面一大串都是无关信息。

其实很简单,就是在二维坐标里面给出若干个圆(阴影),给出起始点和终止点。

问从起始点到终止点,怎么走可以使暴露在非阴影下的路径最短。输出最短路的值。


思路:其实很简单,刚一看,设计到圆面积感觉比较有点蒙,其实圆可以当成点来处理,如果要进去某个圆。

则朝着这个圆的圆心的直线方向走肯定是最短。所以就可以抽象成一个图。每个圆也是一个点。

点与点的路径和圆半径有关,构图时候注意一下即可。

然后dijstra算法。


#include<iostream>
//#include<stdio.h>
#include<math.h>
//#include<memory.h>
//#define min(a,b) (a<b?a:b)
//#define max(a,b) (a>b?a:b)
using namespace std;
const int N=1005;
const double inf=40000.0;
double mat[N][N];
int n;
struct Node
{
    double x;double y;
}s,t;
struct Node2
{
    double x,y,r;
}circle[N];
double dis[N];
bool vis[N];
void dij()
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<=n+1;i++)
        dis[i]=inf;
    dis[0]=0.0;
    vis[0]=true;
    int now=0;
    for(int i=1;i<=n+1;i++)
    {
        double mn=inf;
        int k=-1;
        for(int j=1;j<=n+1;j++)
        {
            if(!vis[j])
            {
                if(mat[now][j]!=inf&&mat[now][j]+dis[now]<dis[j])
                {
                    dis[j]=mat[now][j]+dis[now];
                }
                if(dis[j]<mn)
                    mn=dis[j],k=j;
            }
        }
        now=k;
        vis[now]=true;
        if(now==n+1)
        {    
            printf("%.3lf\n",dis[n+1]);
            break;
        }
    }
    
}
void solve()
{
    for(int i=1;i<=n;i++)
    {
        mat[0][i]=mat[i][0]=sqrt((circle[i].x-s.x)*(circle[i].x-s.x)+(circle[i].y-s.y)*(circle[i].y-s.y))-circle[i].r;
        if(mat[0][i]<0.0)
            mat[0][i]=mat[i][0]=0.0;
        mat[n+1][i]=(mat[i][n+1]=sqrt((circle[i].x-t.x)*(circle[i].x-t.x)
            +(circle[i].y-t.y)*(circle[i].y-t.y))-circle[i].r);
        if(mat[n+1][i]<0.0)
            mat[n+1][i]=mat[i][n+1]=0.0;
        for(int j=i+1;j<=n;j++)
        {
            mat[i][j]=mat[j][i]=(sqrt((circle[i].x-circle[j].x)*(circle[i].x-circle[j].x)+(circle[i].y-circle[j].y)*(circle[i].y-circle[j].y))-circle[i].r-circle[j].r);
            if(mat[i][j]<0.0)
                mat[i][j]=mat[j][i]=0.0;
        }
    }
    mat[0][n+1]=mat[n+1][0]=sqrt((t.x-s.x)*(t.x-s.x)+(t.y-s.y)*(t.y-s.y));
    dij();
}
int main()
{
    
    int cases;
    scanf("%d",&cases);
    while(cases--)
    {
        scanf("%d",&n);
        memset(circle,0,sizeof(circle));
        for(int i=0;i<=n+1;i++)
            for(int j=0;j<=n+1;j++)
                mat[i][j]=inf;
        scanf("%lf%lf%lf%lf",&s.x,&s.y,&t.x,&t.y);
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf",&circle[i].x,&circle[i].y,&circle[i].r);
        }
        solve();
    }
}

你可能感兴趣的:(BOJ1509 海边 dijstra 最短路)