poj 2451 (半平面求交)

来源:互联网 发布:js数组中对象的属性 编辑:程序博客网 时间:2024/05/22 12:45

半平面求交,按着zzy论文里的方法对着写就可以了,这题数据还是比较厚道的

#include<stdio.h>#include<math.h>#include<algorithm>using namespace std;#define eps 1e-8const int maxn=20005;int dcmp(double k){    return (k>eps)-(k<-eps);}struct point{    double x,y;    point(double xx=0,double yy=0){ x=xx;y=yy;}    point rev(point r){ return point(2*x-r.x,2*y-r.y);}    point operator-(point r){ return point(x-r.x,y-r.y);}    point operator+(point r){ return point(x+r.x,y+r.y);}    bool operator==(point r){ return !dcmp(x-r.x)&&!dcmp(y-r.y);}    int operator*(point r){ return dcmp(r.x*y-x*r.y);}    void print(){ printf("(%lf,%lf)\n",x,y);}}p_down[maxn],p_up[maxn],list[maxn];struct line{    point u,v;    line(point uu=point(0,0),point vv=point(0,0)){ u=uu;v=vv;}    void init(){ scanf("%lf%lf%lf%lf",&u.x,&u.y,&v.x,&v.y);}    int operator*(line r){ return (v-u)*(r.v-r.u);}    bool str(){ return !dcmp(u.x-v.x)&&dcmp(v.y-u.y)<0;}    void print(){ printf("(%lf,%lf),(%lf,%lf)\n",u.x,u.y,v.x,v.y);}}q[maxn],l_down[maxn],l_up[maxn],pivot,l1,l2,l3,l4;point intersection(point u1,point u2,point v1,point v2){//直线交点point ret=u1;double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));ret.x+=(u2.x-u1.x)*t;ret.y+=(u2.y-u1.y)*t;return ret;}double area_polygon(point* p,int k){//多边形面积double s1=0,s2=0;for(int i=0;i<k;i++)s1+=p[(i+1)%k].y*p[i].x,s2+=p[(i+1)%k].y*p[(i+2)%k].x;return fabs(s1-s2)/2;}int cmp(line a,line b){    return a*b<0||a.str()&&!b.str();}bool is_left(line a,line b){    return a*line(a.u,b.v)>0;}int n;int cnt_down,cnt_up;int top_down,top_up;void init(){    l1=line(point(-1,0),point(10001,0));    l2=line(point(10001,10000),point(-1,10000));    l3=line(point(10000,-1),point(10000,10001));    l4=line(point(0,10001),point(0,-1));    q[0]=l1;q[1]=l2;q[2]=l3;q[3]=l4;    n+=4;    for(int i=4;i<n;i++) q[i].init();    cnt_down=cnt_up=0;    for(int i=0;i<n;i++){        if(q[i]*pivot>=0) l_down[cnt_down++]=q[i];        else l_up[cnt_up++]=q[i];    }    sort(l_down,l_down+cnt_down,cmp);    sort(l_up,l_up+cnt_up,cmp);    int ct1,ct2;    ct1=1;    for(int i=1;i<cnt_down;i++){        if(l_down[i]*l_down[ct1-1]>0) l_down[ct1++]=l_down[i];        else if(is_left(l_down[i],l_down[ct1-1])) l_down[ct1-1]=l_down[i];    }    cnt_down=ct1;    ct2=1;    for(int i=1;i<cnt_up;i++){        if(l_up[i]*l_up[ct2-1]>0) l_up[ct2++]=l_up[i];        else if(is_left(l_up[i],l_up[ct2-1])) l_up[ct2-1]=l_up[i];    }    cnt_up=ct2;    top_down=0;    p_down[0]=l_down[0].u;    point rear,now;    rear=l_down[0].v;    for(int i=1;i<cnt_down;i++){        point now=intersection(p_down[top_down],rear,l_down[i].u,l_down[i].v);        while(top_down&&now.x<=p_down[top_down].x){            top_down--;            now=intersection(p_down[top_down],p_down[top_down+1],l_down[i].u,l_down[i].v);        }        p_down[++top_down]=now;        rear=l_down[i].v==now?l_down[i].u:l_down[i].v;    }    p_down[++top_down]=rear;    int t1=(p_down[1]-p_down[0])*point(0,-1);    int t2=(p_down[top_down]-p_down[top_down-1])*point(0,-1);    if(t1<0||t1==0&&p_down[1].y>p_down[0].y) p_down[0]=p_down[1].rev(p_down[0]);    if(t2<0||t2==0&&p_down[top_down].y<p_down[top_down-1].y) p_down[top_down]=p_down[top_down-1].rev(p_down[top_down]);    top_up=0;    p_up[0]=l_up[0].u;    rear=l_up[0].v;    for(int i=1;i<cnt_up;i++){        point now=intersection(p_up[top_up],rear,l_up[i].u,l_up[i].v);        while(top_up&&now.x>=p_up[top_up].x){            top_up--;            now=intersection(p_up[top_up],p_up[top_up+1],l_up[i].u,l_up[i].v);        }        p_up[++top_up]=now;        rear=l_up[i].v==now?l_up[i].u:l_up[i].v;    }    p_up[++top_up]=rear;    if((p_up[1]-p_up[0])*point(0,-1)>=0) p_up[0]=p_up[1].rev(p_up[0]);    if((p_up[top_up]-p_up[top_up-1])*point(0,-1)>=0) p_up[top_up]=p_up[top_up-1].rev(p_up[top_up]);}point ll,rr;int ct1,ct2,p1,p2,p3,p4;double area(){    ct1=1;ct2=top_up-1;    bool find=false;    while(ct1<=top_down&&ct2>=0){        if((p_up[ct2]-p_up[ct2+1])*(p_down[ct1]-p_up[ct2+1])<=0) ct1++;        else if((p_down[ct1]-p_down[ct1-1])*(p_up[ct2]-p_down[ct1-1])>=0) ct2--;        else{            ll=intersection(p_down[ct1-1],p_down[ct1],p_up[ct2],p_up[ct2+1]);            p1=ct2;p2=ct1;            find=true;            break;        }    }    if(!find){        //puts("fail!");        return 0;    }    ct1=top_down-1;ct2=1;    while(ct2<=top_up&ct1>=0){        if((p_down[ct1]-p_down[ct1+1])*(p_up[ct2]-p_down[ct1+1])<=0) ct2++;        else if((p_up[ct2]-p_up[ct2-1])*(p_down[ct1]-p_up[ct2-1])>=0) ct1--;        else{            rr=intersection(p_up[ct2-1],p_up[ct2],p_down[ct1],p_down[ct1+1]);            p3=ct2;p4=ct1;            break;        }    }    int ct=0;    list[ct++]=ll;    for(int i=p1;i>=p3;i--) list[ct++]=p_up[i];    list[ct++]=rr;    for(int i=p4;i>=p2;i--) list[ct++]=p_down[i];    return area_polygon(list,ct);}int main(){    pivot.u=point(0,0);pivot.v=point(0,-1);    while(scanf("%d",&n)!=EOF){        init();        printf("%.1lf\n",area()+eps);    }    return 0;}


 

原创粉丝点击