[最短路][几何][牛客] [国庆集训派对1]-L-New Game

题目描述 

Eagle Jump公司正在开发一款新的游戏。Hifumi Takimoto作为其中的员工,获得了提前试玩的机会。现在她正在试图通过一个迷宫。
这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L1:Ax+By+C1=0, L2:Ax+By+C2=0,还有 n 个圆 。角色在直线上、圆上、园内行走不消耗体力。在其他位置上由S点走到T点消耗的体力为S和T的欧几里得距离。
Hifumi Takimoto想从 L1 出发,走到 L2 。请计算最少需要多少体力。

输入描述:

第一行五个正整数 n,A,B,C1,C2 (1≤ n ≤ 1000, -10000 ≤ A,B,C1,C2 ≤ 10000),其中 A,B 不同时为 0。
接下来 n 行每行三个整数 x,y,r(-10000 ≤ x,y ≤ 10000, 1≤ r ≤ 10000) 表示一个圆心为 (x,y),半径为 r 的圆。

输出描述:

仅一行一个实数表示答案。与正确结果的绝对误差或者相对误差不超过 10-4 即算正确。

示例1

输入

复制

2 0 1 0 -4
0 1 1
1 3 1

输出

复制

0.236068

邻接矩阵建图

四种情况

线到线 距离公式

线到圆 距离公式 - 圆半径

圆到圆 距离公式 - 圆半径R1 - 圆半径 R2 如果小于零 由题为零

圆到线 距离公式 - 圆半径

随后迪杰斯特拉

//#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 10;

int n;
double A, B, C1, C2, x, y;

struct point
{
    double x, y, r;
}arr[MAXN];

double edge[MAXN][MAXN];

double ans[MAXN];
 
struct bfsnode
{
    int now;
    double dis;
    
    bfsnode(ll x, double y)
    {
        now = x;
        dis = y;
    }
 
    bool operator < (const bfsnode ret) const
    {
        return dis > ret.dis;
    }
 
};
 
priority_queue <bfsnode> PQ;
 
bool finded[MAXN];
 
void bfs(bfsnode x)
{
    PQ.push(x);
    
    while(! PQ.empty())
    {
        bfsnode B = PQ.top();
 
        PQ.pop();
 
        if( !finded[B.now] )
        {
            finded[B.now] = true;
 
            ans[B.now] = min(ans[B.now], B.dis);
 
            for(int i = 0; i <= n + 1; i++)
            {
                if(i != B.now)
                    PQ.push( bfsnode(i, B.dis + edge[B.now][i]));
            }
        }
    }
}

//
signed main()
{
    //ios::sync_with_stdio(false);
 
    //cin.tie(0);     cout.tie(0);
 
    
    scanf("%d%lf%lf%lf%lf", &n, &A, &B, &C1, &C2);

    for(int i = 1; i <= n; i++)
        scanf("%lf%lf%lf", &arr[i].x, &arr[i].y, &arr[i].r);
    
    double t;

    for(int i = 1; i <= n; i++)
    {
        t = fabs( (A*arr[i].x + B*arr[i].y + C1) / sqrt(A * A + B * B)) - arr[i].r;
        if(t > 0)
        {
            edge[0][i] = t;
            edge[i][0] = t;
        }
        t = fabs( (A*arr[i].x + B*arr[i].y + C2) / sqrt(A * A + B * B)) - arr[i].r;
        if(t > 0)
        {
            edge[n + 1][i] = t;
            edge[i][n + 1] = t;
        }
    }
    t = fabs(C1 - C2 / sqrt(A*A+B*B));
    edge[0][n+1] = t;
    edge[n+1][0] = t;

    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(i != j)
            {
                t = sqrt( (arr[i].x - arr[j].x) * (arr[i].x - arr[j].x) + (arr[i].y - arr[j].y) * (arr[i].y - arr[j].y) ) - arr[i].r - arr[j].r;
                if(t > 0)
                {
                    edge[i][j] = t;
                    edge[j][i] = t;
                }
               
            }   
        }
    }


    for(int i = 0; i < MAXN; i++)
        ans[i] = 0x3f3f3f3f;

    bfs(bfsnode(0, 0));
 
    // for(int i = 0; i <= n + 1; i++)
    // {
    //     for(int j = 0; j <= n + 1; j++)
    //     {
    //         cout<<edge[i][j]<<' ';
    //     }
    //     cout<<endl;
    // }
    printf("%.8lf\n", ans[n + 1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Zeolim/article/details/82963250