zoukankan      html  css  js  c++  java
  • Luogu3297 SDOI2013逃考(半平面交+最短路)

      把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为1可以直接bfs)。显然存在最优路线没有某个时刻同时被多于两人监视,要到达另一个区域的话完全可以经过分界线而不是和其他区域的交点(若两个区域只有一个交点的话是不能直接到达的),总之就是说不用特判同时被多人监视的情况。

      现在问题是怎么求出哪些监视范围相邻。考虑对于某个人的监视范围求出所有与它相邻的。两个监视范围的公共边是这两个人连线的中垂线,把这些线画出来可以发现求个半平面交就好了。注意线要求在矩形范围内。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 610
    #define vector dot
    int T,n,p[N],d[N],queue[N],cnt;
    bool flag[N];
    const double eps=1E-10;
    struct data{int to,nxt;
    }edge[N*N];
    struct dot
    {
        double x,y;
        vector operator +(const vector&a) const
        {
            return (vector){x+a.x,y+a.y};
        }
        vector operator -(const vector&a) const
        {
            return (vector){x-a.x,y-a.y};
        }
        double operator *(const vector&a) const
        {
            return x*a.y-y*a.x;
        }
        vector operator *(const double a) const
        {
            return (vector){a*x,a*y};
        }
        double len()
        {
            return sqrt(x*x+y*y);
        }
        vector rotate()
        {
            return (vector){-y,x};
        }
    }a[N],P[N];
    struct line
    {
        dot a;vector p;int i;
        bool operator <(const line&a) const
        {
            return atan2(p.x,p.y)>atan2(a.p.x,a.p.y);
        }
    }q[N],Q[N];
    void addedge(int x,int y){cnt++;edge[cnt].to=y,edge[cnt].nxt=p[x],p[x]=cnt;}
    bool onright(line x,dot y)
    {
        return (y-x.a)*x.p>=0;
    }
    dot cross(line x,line y)
    {
        return y.a+y.p*(x.p*(x.a-y.a)/(x.p*y.p));
    }
    int bfs(int S)
    {
        memset(d,42,sizeof(d));
        int head=0,tail=1;queue[1]=S;d[S]=0;
        do
        {
            int x=queue[++head];
            for (int i=p[x];i;i=edge[i].nxt)
            if (d[x]+1<d[edge[i].to])
            {
                d[edge[i].to]=d[x]+1;
                queue[++tail]=edge[i].to;
                if (!edge[i].to) return d[edge[i].to];
            }
        }while (head<tail);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("3297.in","r",stdin);
        freopen("3297.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        T=read();
        while (T--)
        {
            n=read();
            int r=read(),c=read();
            dot s;s.x=read(),s.y=read();
            for (int i=1;i<=n;i++)
            a[i].x=read(),a[i].y=read();
            int S;
            double dis=(a[1]-s).len();
            for (int i=2;i<=n;i++) dis=min(dis,(a[i]-s).len());
            for (int i=1;i<=n;i++) if (fabs(dis-(a[i]-s).len())<eps) S=i;
            cnt=0;
            memset(p,0,sizeof(p));
            for (int j=1;j<=n;j++)
            {
                int t=0;
                for (int i=1;i<=n;i++)
                if (i!=j) q[++t]=(line){(a[i]+a[j])*0.5,(a[i]-a[j]).rotate(),i};
                q[++t]=(line){(dot){0,0},(vector){1,0},0};
                q[++t]=(line){(dot){r,0},(vector){0,1},0};
                q[++t]=(line){(dot){r,c},(vector){-1,0},0};
                q[++t]=(line){(dot){0,c},(vector){0,-1},0};
                sort(q+1,q+t+1);
                int head=1,tail=1;Q[1]=q[1];
                for (int i=2;i<=t;i++)
                {
                    while (head<tail&&onright(q[i],P[tail])) tail--;
                    while (head<tail&&onright(q[i],P[head+1])) head++;
                    Q[++tail]=q[i];
                    if (fabs(Q[tail-1].p*Q[tail].p)<eps)
                    {
                        tail--;
                        if (onright(q[i],Q[tail].a)) Q[tail]=q[i];
                    }
                    if (head<tail) P[tail]=cross(Q[tail],Q[tail-1]);
                }
                while (head<tail&&onright(Q[head],P[tail])) tail--;
                P[head]=cross(Q[head],Q[tail]);
                for (int i=head;i<=tail;i++) addedge(j,Q[i].i);
            }
            printf("%d
    ",bfs(S));
        }
        return 0;
    }
  • 相关阅读:
    BOM
    no response from Graphic Screen Painter Exiting
    Windows Mobile 中模拟按键
    C# 获取汉字拼音首字母
    Web Service介绍
    .net/c#中栈和堆的区别及代码在栈和堆中的执行流程详解
    使用JSON加速AJAX(By Sean Kelly)
    Sql字符串操作函数
    一个简单AJAX注册示例
    .Net平台开发的技术规范与实践精华总结
  • 原文地址:https://www.cnblogs.com/Gloid/p/9418277.html
Copyright © 2011-2022 走看看