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

    题意

    两个亲戚间的范围的分界线必定为两者连线的中垂线,因此我们用半平面交(O(n^2log n))求出每个人的范围,之后相邻的两个范围连边跑最短路即可。

    注意特判(n=0)的情况。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=610;
    const double eps=1e-8;
    const double inf=1e12;
    const double Pi=acos(-1.0);
    int T,n,m,tot,cnt_edge,st;
    int head[maxn],dis[maxn];
    double sx,sy,limx,limy;
    bool vis[maxn];
    struct edge{int to,nxt;}e[maxn*maxn];
    inline void add_edge(int u,int v)
    {
    	e[++cnt_edge].nxt=head[u];
    	head[u]=cnt_edge;
    	e[cnt_edge].to=v;
    }
    struct Point
    {
        double x,y;
        inline double len(){return sqrt(x*x+y*y);}
        Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
        Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
        Point operator*(const double k){return (Point){x*k,y*k};}
        Point operator/(const double k){return (Point){x/k,y/k};}
        double operator*(const Point a)const{return x*a.y-y*a.x;}
        double operator&(const Point a)const{return x*a.x+y*a.y;}
    }p[maxn];
    inline int dcmp(double x)
    {
        if(fabs(x)<=eps)return 0;
        return x<0?-1:1;
    } 
    inline Point get(Point a,Point b){return b-a;}
    inline Point turn(Point a,double theta){return (Point){-a.y,a.x};}
    struct Line
    {
        Point p,v;int id;double theta;
        bool operator<(const Line& a)const
        {
            return !dcmp(theta-a.theta)?dcmp(get(p,v)*get(p,a.v))<0:dcmp(theta-a.theta)<0;
        }
    }line[maxn],q[maxn];
    inline Point getpoint(Line l1,Line l2)
    {
        Point p1=l1.p,v1=l1.v,p2=l2.p,v2=l2.v;
        v1=get(p1,v1),v2=get(p2,v2);
        Point u=get(p1,p2);
        return p2+v2*(u*v1)/(v1*v2);
    }
    inline bool check(Line a,Line b,Line c)
    {
        Point p=getpoint(a,b);
        return dcmp(get(c.p,c.v)*get(c.p,p))<=0;
    }
    inline void solve(int id)
    {
        for(int i=1;i<=tot;i++)line[i].theta=atan2(line[i].v.y-line[i].p.y,line[i].v.x-line[i].p.x);
        sort(line+1,line+tot+1);
        int cnt=0;line[0].theta=inf;
        for(int i=1;i<=tot;i++)if(line[i].theta!=line[i-1].theta)line[++cnt]=line[i];
        tot=cnt;
        int l,r;
        q[l=r=1]=line[1];q[++r]=line[2];
        for(int i=3;i<=tot;i++)
        {
            while(l<r&&check(q[r-1],q[r],line[i]))r--;
            while(l<r&&check(q[l],q[l+1],line[i]))l++;
            q[++r]=line[i];
        }
        while(l<r&&check(q[r-1],q[r],q[l]))r--;
        while(l<r&&check(q[l],q[l+1],q[r]))l++;
        for(int i=l;i<=r;i++)add_edge(id,q[i].id);
        bool flag=1;
        for(int i=l;i<=r;i++)if(dcmp(get(q[i].p,q[i].v)*get(q[i].p,(Point){sx,sy}))<=0)flag=0;
        if(flag)st=id;
    }
    inline Line get_line(int x,int y)
    {
    	Point z=(p[x]+p[y])/2.0;
    	return (Line){z,z+turn(get(p[x],p[y]),Pi/2.0),y,0};
    }
    inline void work(int id)
    {
    	tot=0;
    	Point p1=(Point){0,0},p2=(Point){limx,0},p3=(Point){limx,limy},p4=(Point){0,limy};
    	line[++tot]=(Line){p1,p2,n+1,0};
    	line[++tot]=(Line){p2,p3,n+1,0};
    	line[++tot]=(Line){p3,p4,n+1,0};
    	line[++tot]=(Line){p4,p1,n+1,0};
    	for(int i=1;i<=n;i++)if(i!=id)line[++tot]=get_line(id,i);
    	solve(id);
    }
    inline void spfa()
    {
    	memset(dis,0x3f,sizeof(dis));
    	queue<int>q;
    	q.push(st);dis[st]=0;vis[st]=1;
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();vis[x]=0;
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int y=e[i].to;
    			if(dis[y]>dis[x]+1)
    			{
    				dis[y]=dis[x]+1;
    				if(!vis[y])q.push(y),vis[y]=1;
    			}
    		}
    	}
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	scanf("%d",&T);
    	while(T--)
    	{
    		memset(head,0,sizeof(head));
    		cnt_edge=st=0;
    		scanf("%d",&n);
    		scanf("%lf%lf%lf%lf",&limx,&limy,&sx,&sy);
    		for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
    		if(!n){puts("0");continue;}
    		for(int i=1;i<=n;i++)work(i);
    		spfa();
    		printf("%d
    ",dis[n+1]);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    ajax与Servlet
    Myeclipse快捷键的设置以及默认的编码格式
    bootstrap02导航菜单
    bootstrap01登录小例子
    ajax
    面向对象04异常
    mysql
    Day10 Python基础之特殊函数(八)
    Day9 Python基础之函数基础(七)
    Day8 Python基础之遗漏知识点(六)
  • 原文地址:https://www.cnblogs.com/nofind/p/12244717.html
Copyright © 2011-2022 走看看