SGU 198 Get Out!(SPFA+计算几何)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=198

题意:平面上有一堆圆,再给出一个圆P,问P能否在其他圆的缝隙中穿过到达无穷远处?

思路:将P看做一个点,然后将其他圆的半径都加上一个P的半径。接着其他圆任意两个相交则连线表示P不能通过这两个圆。然后判断是有存在一个环包含P。









class point

{

public:

    double x,y;



    point(){}

    point(double _x,double _y)

    {

        x=_x;

        y=_y;

    }



    void get()

    {

        RD(x,y);

    }



    point operator-(point a)

    {

        return point(x-a.x,y-a.y);

    }



    double operator*(point a)

    {

        return x*a.y-y*a.x;

    }



    double operator^(point a)

    {

        return x*a.x+y*a.y;

    }



    double getLen()

    {

        return sqrt(x*x+y*y);

    }



    double getAng(point a)

    {

        return atan2(*this*a,*this^a);

    }

};



int n,g[305][305],t[305];

point a[305];

double p[305][305],dis[305],r[305];



int DB(double x)

{

    if(x>1e-10) return 1;

    if(x<-1e-10) return -1;

    return 0;

}



void SPFA()

{

    queue<int> Q;

    int inq[305]={0},i,j,k;

    FOR0(i,n) Q.push(i),inq[i]=1;

    while(!Q.empty())

    {

        k=Q.front();

        Q.pop();



        inq[k]=0;

        FOR0(i,n) if(g[k][i]&&DB(dis[k]+p[k][i]-dis[i])<0)

        {

            dis[i]=dis[k]+p[k][i];

            if(inq[i]) continue;

            inq[i]=1;

            Q.push(i);

            if(++t[i]>n)

            {

                puts("NO");

                return;

            }

        }

    }

    puts("YES");

}



int main()

{

    RD(n);

    int i,j;

    FOR0(i,n+1) a[i].get(),RD(r[i]);

    FOR0(i,n) FOR0(j,n) if(i!=j)

    {

        if(DB(r[i]+r[j]+r[n]*2-(a[i]-a[j]).getLen())>0)

        {

            g[i][j]=1;

            p[i][j]=(a[i]-a[n]).getAng(a[j]-a[n]);

        }

    }

    SPFA();

    return 0;

}

  

你可能感兴趣的:(SPFA)