POJ-3130 How I Mathematician Wonder What You Are!

半平面交第一题 !

题意是给出一个多边形,问他是否存在内核,即“可以看到任何一个地方的区域”。

内核即半平面交,下面是离线求半平面交的\(nlogn\)算法

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100;
struct Point{
    double x,y;
    Point(double xx=0,double yy=0){
        x=xx,y=yy;
    }
}a[maxn],p[maxn];
struct Vector{
    double x,y;
    Vector(double xx=0,double yy=0){
        x=xx,y=yy;
    }
};
struct Line{
    Point p;
    Vector v;
    double ang;
    Line(Point a=Point(),Vector b=Vector()){
        p=a,v=b;
        ang=atan2(b.y,b.x);
    }
}b[maxn],q[maxn];
int dcmp(double x){return fabs(x)<1e-9?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Vector operator * (double p,Vector a){return Vector(a.x*p,a.y*p);}
Vector operator * (Vector a,double p){return Vector(a.x*p,a.y*p);}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
bool operator < (Line a,Line b){return a.ang<b.ang;}
bool onleft(Line a,Point b){return dcmp(a.v*(b-a.p))>0;}
Point glt(Point a,Point b,Point c,Point d){
    Vector v1=b-a,v2=d-c,v3=a-c;
    return a+v2*v3/(v1*v2)*v1;
}
int n,l,r;
void bpm(){
    sort(b+1,b+n+1);
    l=r=1;
    q[1]=b[1]; //先加入第一条
    for(int i=2;i<=n;i++){
        while(l<r&&!onleft(b[i],p[r-1])) r--;
        while(l<r&&!onleft(b[i],p[l])) l++;  //如果不在左边就弹出去
        q[++r]=b[i];
        if(dcmp(b[i].v*q[r-1].v)==0){
            r--;
            if(onleft(q[r],b[i].p))  //这个应该是如果两个重合,就先把b[i]加入
                q[r]=b[i];
        }
        if(l<r)
            p[r-1]=glt(q[r-1].p,q[r-1].p+q[r-1].v,q[r].p,q[r].p+q[r].v); //交点更新
    }
    while(l<r&&!onleft(q[l],p[r-1])) r--;  //有可能最后加入的几条是不合法的,要弹出来
}
int main(){
//  freopen("3130.in","r",stdin);
    while(1){
        scanf("%d",&n);
        if(n==0) break;
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        for(int i=1;i<n;i++)
            b[i]=Line(a[i],a[i+1]-a[i]);
        b[n]=Line(a[n],a[1]-a[n]);
        bpm();
        if(r-l<=1) printf("0\n");
        else printf("1\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nianheng/p/10010139.html
今日推荐