luogu P3297 [SDOI2013]逃考

传送门

gugugu

首先每个人管理的区域是一个多边形,并且整个矩形是被这样的多边形填满的.现在的问题是求一条经过多边形最少的路径到达边界,这个可以最短路.

现在的问题是建图,显然我们应该给相邻的多边形连边,考虑一个人和另一个人的多边形交界线,这个线就是两点线段的中垂线,于是我们可以每次把一个人所有的分界线和矩形边界拿出来求一个半平面交,如果某条边在半平面交上就和对应点连边就好了,矩形边界在半平面交上就和外面连边.最后求起点所在多边形到外面的最短路

然后我半平面交写错,就写了半天qwq

#include<bits/stdc++.h>
#define LL long long
#define db long double
#define il inline

using namespace std;
const int N=600+10;
const db eps=1e-10;
il LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N*N],nt[N*N],hd[N],tot;
void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;}
struct point
{
    db x,y;
    point(){}
    point(db nx,db ny){x=nx,y=ny;}
    point operator - (const point &bb) const {return point(x-bb.x,y-bb.y);}
    db operator * (const point &bb) const {return x*bb.x+y*bb.y;}
    db operator ^ (const point &bb) const {return x*bb.y-y*bb.x;}
}a[N],sht;
db sq(db x){return x*x;}
db dis(point aa,point bb){return sqrt(sq(bb.x-aa.x)+sq(bb.y-aa.y));}
db ang(point aa,point bb){return atan2((bb.y-aa.y),(bb.x-aa.x));}
struct line
{
    int ii;
    point x,y;
    db k,b,ag;
    line(){}
    line(int id,point nx,point ny)
    {
        ii=id;
        x=nx,y=ny;
        k=fabs(x.x-y.x)>eps?(x.y-y.y)/(x.x-y.x):1e18;
        b=k<1e17?x.y-k*x.x:x.x;
        ag=ang(x,y);
    }
    bool operator < (const line &bb) const {return fabs(ag-bb.ag)>eps?ag<bb.ag:dis(sht,x)<dis(sht,bb.x);}
}lb[N],q[N];
point jiao(line aa,line bb)
{
    db x=max(aa.k,bb.k)<1e17?(bb.b-aa.b)/(aa.k-bb.k):(aa.k>bb.k?aa.b:bb.b);
    db y=aa.k<bb.k?aa.k*x+aa.b:bb.k*x+bb.b;
    return point(x,y);
}
int n,tp;
int ll,rr,di[N];
bool v[N];
db mx,my,sx,sy;

int main()
{
    int T=rd();
    while(T--)
    {
        memset(hd,0,sizeof(hd)),tot=0;
        n=rd();
        mx=rd(),my=rd(),sx=rd(),sy=rd();
        for(int i=1;i<=n;++i)
        {
            int x=rd(),y=rd();
            a[i]=point(x,y);
        }
        lb[0].ag=-2333;
        for(int i=1;i<=n;++i)
        {
            sht=a[i];
            int m=0;
            for(int j=1;j<=n;++j)
                if(i!=j)
                {
                    point md=point((a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2);
                    db kk=fabs(a[i].x-a[j].x)>eps?-1/((a[i].y-a[j].y)/(a[i].x-a[j].x)):0,bb=md.y-kk*md.x;
                    point xx=point(md.x-1,kk*(md.x-1)+bb),yy=point(md.x+1,kk*(md.x+1)+bb);
                    if(fabs(a[i].y-a[j].y)<eps) xx=point(md.x,md.y-1),yy=point(md.x,md.y+1);
                    if(((xx-a[i])^(yy-a[i]))<eps) swap(xx,yy);
                    lb[++m]=line(j,xx,yy);
                }
            lb[++m]=line(0,point(0,my),point(0,0));
            lb[++m]=line(0,point(mx,my),point(0,my));
            lb[++m]=line(0,point(mx,0),point(mx,my));
            lb[++m]=line(0,point(0,0),point(mx,0));
            sort(lb+1,lb+m+1);
            int las=m;
            m=0;
            for(int j=1;j<=las;++j)
                if(fabs(lb[j].ag-lb[j-1].ag)>eps) lb[++m]=lb[j];
            ll=1,q[rr=1]=lb[1];
            for(int j=2;j<=m;++j)
            {
                while(ll<rr&&((lb[j].y-lb[j].x)^(jiao(q[rr],q[rr-1])-lb[j].x))<eps) --rr;
                while(ll<rr&&((lb[j].y-lb[j].x)^(jiao(q[ll],q[ll+1])-lb[j].x))<eps) ++ll;
                q[++rr]=lb[j];
            }
            while(ll<rr&&((q[ll].y-q[ll].x)^(jiao(q[rr],q[rr-1])-q[ll].x))<eps) --rr;
            for(int j=ll;j<=rr;++j) add(i,q[j].ii);
        }
        int sta=0;
        db ma=1e17;
        for(int i=1;i<=n;++i)
            if(ma>=dis(point(sx,sy),a[i]))
                ma=dis(point(sx,sy),a[i]),sta=i;
        queue<int> qq;
        memset(di,0x3f3f3f,sizeof(di));
        di[sta]=0,v[sta]=1,qq.push(sta);
        while(!qq.empty())
        {
            int x=qq.front();
            qq.pop();
            v[x]=0;
            for(int i=hd[x];i;i=nt[i])
            {
                int y=to[i];
                if(di[y]>di[x]+1)
                {
                    di[y]=di[x]+1;
                    if(!v[y]) v[y]=1,qq.push(y);
                }
            }
        }
        printf("%d\n",di[0]);
    }
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/smyjr/p/10659665.html