半平面求交,按着zzy论文里的方法对着写就可以了,这题数据还是比较厚道的
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define eps 1e-8
const 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;
}