L - New Game(单源最短路之dijkstra)

版权声明:Andy https://blog.csdn.net/Alibaba_lhl/article/details/83049039

Description

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 即算正确。

Sample Input

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

Sample Output

0.236068

Source::传送门

题解

可以将这个问题看成最短路问题来进行求解。关键在于如何建图:将线和圆都看成一个个点。每个点之间的距离满足下列关系:

L1->L2边权 = L1到L2的距离。

线L到圆i边权 = max( 0 , dis(L,O(i)) - r(i) )。

圆i 到 圆j 边权 = max( 0 , dis(O(i) , O(j)) - r(i) - r(j) )。

然后直接求最短路即可。

                                                                                                                                                                                              

AC Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = (int)1e3+10;
const double INF = 0x3f3f3f3f;

double n, A, B, C1, C2;
bool vis[MAXN];
double dis[MAXN];
double mmp[MAXN][MAXN];
struct Data
{
    double x, y, r;
}st[MAXN];

double dis1(double x1, double y1, double x2, double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double dis2(double C, double x, double y)
{
    return fabs(A*x+B*y+C) / sqrt(A*A+B*B);
}
void getmap()
{
    scanf("%lf %lf %lf %lf %lf",&n,&A,&B,&C1,&C2);
    for(int i=3; i<=n+2; i++)
    {
        scanf("%lf %lf %lf",&st[i].x,&st[i].y,&st[i].r);
    }
    for(int i=1; i<=n+2; i++)
    {
        for(int j=1; j<=n+2; j++)
        {
            if(i==j) mmp[i][j] = 0;
            else mmp[i][j] = mmp[j][i] = INF;
        }
    }
    mmp[1][2] = mmp[2][1] = fabs(C1-C2) / sqrt(A*A+B*B);
    int s = 0;
    for(int i=1; i<=n+2; i++)
    {
        for(int j=1; j<=n+2; j++)
        {
            if(i==j) continue;
            if( (i==1 && j==2) || (i==2 && j==1) ) continue;
            if(i==1)
            {
                mmp[i][j] = max( (dis2(C1,st[j].x,st[j].y) - st[j].r), 0.0);
            }
            else if(i==2)
            {
                mmp[i][j] = max( (dis2(C2,st[j].x,st[j].y) - st[j].r), 0.0);
            }
            else if(j==1)
            {
                mmp[i][j] = max( (dis2(C1,st[i].x,st[i].y) - st[i].r), 0.0);
            }
            else if(j==2)
            {
                mmp[i][j] = max( (dis2(C2,st[i].x,st[i].y) - st[i].r), 0.0);
            }
            else
            {
                mmp[i][j] = max( dis1(st[i].x,st[i].y,st[j].x,st[j].y)-st[i].r-st[j].r, 0.0);
            }
        }
    }
}
void djk(int st, int ed)
{
    for(int i=1; i<=n+2; i++)
    {
        vis[i] = false;
        dis[i] = mmp[st][i];
    }
    vis[st] = true;
    for(int i=1; i<=n+1; i++)
    {
        int id = -1;
        double mn = INF;
        for(int j=1; j<=n+2; j++)
        {
            if(!vis[j] && dis[j]<mn)
            {
                id = j;
                mn = dis[j];
            }
        }
        if(id==-1) break;
        vis[id] = true;
        for(int j=1; j<=n+2; j++)
        {
            if(!vis[j] && mmp[i][j]!=INF)
            {
                if(dis[j]>mn+mmp[id][j])
                {
                    dis[j] = mn + mmp[id][j];
                }
            }
        }
    }
    cout<< dis[ed] << endl;
}
int main()
{
    getmap();
    djk(1,2);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Alibaba_lhl/article/details/83049039