zoukankan      html  css  js  c++  java
  • P3297 [SDOI2013]逃考

    传送门

    完全看不出这思路是怎么来的……

    首先对于两个亲戚,他们监视范围的边界是他们连线的中垂线。那么对于一个亲戚来说它能监视的范围就是所有的中垂线形成的半平面交

    然后如果某两个亲戚的监视范围有公共边,那么就在这两个亲戚之间连一条边,如果某个亲戚的监视范围和矩阵边界有公共边,那么就把这个亲戚和终点连边。然后以一开始监视的亲戚为起点,跑一遍最短路即可

    //minamoto
    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
    #define go(u) for(register int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    using namespace std;
    int read(){
        int res,f=1;char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=10005;
    int S,T,n,times,sx,sy,bx,by,no[N],m;
    struct Graph{
        struct eg{int v,nx;}e[N<<1];int head[N],tot;
        inline void clr(){tot=0;memset(head,0,sizeof(head));}
        inline void add(int u,int v){e[++tot]={v,head[u]},head[u]=tot;}
        int dis[N],q[N];bool vis[N];
        int spfa(){
            fp(i,1,n+1)dis[i]=inf,vis[i]=0;
            int h=0,t=1;dis[S]=0,q[h]=S;
            while(h!=t){
                int u=q[h++];vis[u]=0;if(h==N)h-=N;
                go(u)if(dis[v]>dis[u]+1){
                    dis[v]=dis[u]+1;
                    if(!vis[v]){
                        q[t++]=v,vis[v]=1;
                        if(t==N)t-=N;
                    }
                }
            }return dis[T];
        }
    }G;
    struct node{double x,y;}p[N];
    struct line{
        node a,b;int id;double sl;
        inline line(){}
        inline line(node a,node b,int id):a(a),b(b),id(id){sl=atan2(b.y-a.y,b.x-a.x);}
    }q[N],a[N],l[N];
    inline node operator +(node a,node b){return {a.x+b.x,a.y+b.y};}
    inline node operator -(node a,node b){return {a.x-b.x,a.y-b.y};}
    inline double operator *(node a,node b){return a.x*b.y-a.y*b.x;}
    inline bool operator <(line a,line b){return a.sl==b.sl?(a.b-a.a)*(b.a-a.a)<=0:a.sl<b.sl;}
    node inter(line a,line b){
        double k1,k2,t;
        k1=(b.b-a.a)*(a.b-a.a);
        k2=(a.b-a.a)*(b.a-a.a);
        t=k2/(k1+k2);
        return {b.a.x+t*(b.b.x-b.a.x),b.a.y+t*(b.b.y-b.a.y)};
    }
    inline bool jd(line a,line b,line c){node p=inter(a,b);return (p-c.a)*(c.b-c.a)>0;}
    void hpi(int st){
        int tot=0;sort(l+1,l+1+m);
        fp(i,1,m)if(l[i].sl!=a[tot].sl)a[++tot]=l[i];
        int h=1,t=0;q[++t]=a[1],q[++t]=a[2];
        fp(i,3,tot){
            while(h<t&&jd(q[t-1],q[t],a[i]))--t;
            while(h<t&&jd(q[h+1],q[h],a[i]))++h;
            q[++t]=a[i];
        }
        while(h<t&&jd(q[t-1],q[t],q[h]))--t;
        while(h<t&&jd(q[h+1],q[h],q[t]))++h;
        fp(i,h,t)G.add(st,q[i].id);
    }
    void clr(){G.clr(),memset(no,0,sizeof(no));}
    double dis(node a,node b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
    node rotate(node a){return {-a.y,a.x};}
    node getmid(node a,node b){return {(a.x+b.x)/2,(a.y+b.y)/2};}
    void init(int st){
        l[1]=line({0,0},{sx,0},n+1),l[2]=line({sx,0},{sx,sy},n+1);
        l[3]=line({sx,sy},{0,sy},n+1),l[4]=line({0,sy},{0,0},n+1);
        m=4;
        fp(i,1,n)if(i!=st&&!no[i]){
            node mid=getmid(p[i],p[st]);
            node v=rotate(p[i]-p[st]);
            l[++m]=line(mid,mid+v,i);
        }
    }
    void solve(){
        clr(),n=read(),sx=read(),sy=read(),bx=read(),by=read();
        node res={bx,by};
        if(!n)return (void)(puts("0"));
        T=n+1;int pos=0;double len=1e15;
        fp(i,1,n){
            p[i].x=read(),p[i].y=read();
            if(p[i].x>sx||p[i].y>sy)no[i]=1;
            double now=dis(p[i],res);
            if(now<len)len=now,pos=i;
        }S=pos;
        fp(i,1,n)if(!no[i])init(i),hpi(i);
        printf("%d
    ",G.spfa());
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
        times=read();
        while(times--)solve();
        return 0;
    }
    
  • 相关阅读:
    《PS技巧精华全部在这里!》
    c#的dictionary为什么在扩容时会以素数扩容
    初识Lua
    常用的排序
    像gal一样讲故事~
    打枪的实现
    武器的方向,人物和武器的翻转
    虚拟摇杆的修改
    实现虚拟摇杆的移动
    itemPool和MessageCenter
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10039119.html
Copyright © 2011-2022 走看看