凸包
poj 1113 Graham Scan 算法 极角排序+栈模拟
//#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps=1e-8; const double pi=acos(-1.0); inline double sqr(double x) { return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } Point operator -(const Point &b)const { return Point(x-b.x,y-b.y); } }; double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //点积 bool up(Point a,Point b){ if(a.y==b.y) return a.x<b.x; return a.y<b.y; } bool cmp(Point a, Point b)//先按象限排序,再按极角排序,再按远近排序 (调精度 注意改成int或ll) { if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x; if (a.y == 0 && a.x >= 0 && b.y != 0)return true; if (b.y == 0 && b.x >= 0 && a.y != 0)return false; if (b.y*a.y <= 0)return a.y>b.y; Point one; one.y = one.x = 0; return cross(one-a,one-b) > 0 || (cross(one-a,one-b) == 0 && a.x < b.x); } const int maxn=1e3+10; Point pa[maxn]; int st[maxn]; // void Graham(int n,int r){ sort(pa,pa+n,up); for(int i=1;i<n;i++) { pa[i]=pa[i]-pa[0]; } pa[0]=pa[0]-pa[0]; sort(pa+1,pa+n,cmp); st[0]=0; st[1]=1; int top=1; for(int i=2;i<n;i++){ while(top>=1 && cross(pa[st[top]]-pa[st[top-1]],pa[i]-pa[st[top]])<=0) top--; st[++top]=i; } double ans=0; for(int i=0;i<=top;i++){ ans+=dis(pa[st[i]],pa[st[(i+1)%(top+1)]]); } printf("%.0f\n",ans+pi*r*2); } int main(){ int n; scanf("%d",&n); int r; scanf("%d",&r); for(int i=0;i<n;i++) scanf("%lf %lf",&pa[i].x,&pa[i].y); Graham(n,r); return 0; }
poj 1113 求上下凸包 求出整个凸包 排序+上凸包+下凸包
#include <iostream> #include <cstdio> #include <cstring> //#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps=1e-8; const double pi=acos(-1.0); inline double sqr(double x) { return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } Point operator -(const Point &b)const { return Point(x-b.x,y-b.y); } }; double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //点积 const int maxn=1e3+10; Point pa[maxn],pt[maxn]; bool up(Point a,Point b){ if(a.x!=b.x) return a.x<b.x; return a.y<b.y; } int main(){ int n,r; scanf("%d %d",&n,&r); for(int i=0;i<n;i++) scanf("%lf %lf",&pa[i].x,&pa[i].y); sort(pa,pa+n,up); int m=0; for(int i=0;i<n;i++){ while(m>1 && cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } int k=m; for(int i=n-2;i>=0;i--){ while(m>k && cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } if(n>1) m--; double ans=0; for(int i=1;i<m;i++) ans+=dis(pt[i],pt[i+1]); ans+=dis(pt[m],pt[1]); ans+=pi*r*2; printf("%.0f\n",ans); return 0; }
半平面交
poj 3335 多边形求核
//#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps=1e-8; const double EPS=eps; const double pi=acos(-1.0); const double PI=pi; inline double sqr(double x){ return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} }; struct Line{ Point s,e; // s-> 起始点 e->终点 Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x+=(e.x-s.x)*t; res.y+=(e.y-s.y)*t; return res; } }; double get_angle(Point a){ return atan2(a.y,a.x); }// [-PI PI] double get_angle(Line a) { return atan2(a.e.y-a.s.y,a.e.x-a.s.x); } bool judge(Point *pa,int n){ // 用多边形面积来判断正负 double ans = 0; for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); } return ans>=0; } bool cmp(Line a,Line b){ // 极角排序 同极角左边就ok了 Point va=a.e-a.s; double x=get_angle(va); Point vb=b.e-b.s; double y=get_angle(vb); if(fabs(x-y)<eps) { return (va^(b.e-a.s))>=0; } // 射线的左右 注意和直线区别 else return x<y; } bool onright(Line a,Line b,Line c){ /*Point o=b&c; // 判断 o 是否在a右边 if( ((a.e-o)^(a.s-o))>0 ) return true; return false;*/ Point o = b&c; if (((a.e - a.s) ^ (o - a.s)) < 0) return true; return false; } const int maxn=1e2+10; Point pa[maxn]; Line que[maxn],la[maxn]; bool HalfPlaneIntersection(Line *la,int n){ sort(la,la+n,cmp); int head=0,tail=0,cnt=0; // 栈模拟 for (int i=0;i<n-1;i++) { if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) { // 去掉极角相同的(右边边的没用...) continue; }la[cnt++]=la[i]; }la[cnt++]=la[n-1]; for(int i=0;i<cnt;i++){ //cout<<la[i].s.x<<" "<<la[i].s.y<<"->"<<la[i].e.x<<" "<<la[i].e.y<<endl; while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(la[i],que[head],que[head+1])) head++; que[tail++]=la[i]; } while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(que[tail-1],que[head],que[head+1])) head++; if(tail-head<3) return false; return true; } int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%lf %lf",&pa[i].x,&pa[i].y); } if(judge(pa,n)){ for(int i=0;i<n;i++) la[i]=Line(pa[i],pa[(i+1)%n]);} else { for(int i=0;i<n;i++) la[i]=Line(pa[(i+1)%n],pa[i]);} //for(int i=0;i<n;i++){cout<<la[i].s.x<<" "<<la[i].s.y<<"->"<<la[i].e.x<<" "<<la[i].e.y<<endl;} //cout<<"---"<<endl; bool c=HalfPlaneIntersection(la,n); if(c) printf("YES\n"); else printf("NO\n"); } }
这个写法也OK ONRIGHT
bool onright(Line a,Line b,Line c){ Point o=b&c; // 判断 o 是否在a右边 if( ((a.e-o)^(a.s-o))>0 ) return true; return false; /*Point o = b&c; if (((a.e - a.s) ^ (o - a.s)) < 0) return true; return false;*/ }
大佬博客 和 代码 https://blog.csdn.net/qq_40861916/article/details/83541403
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int maxn = 1e3; const double EPS = 1e-5; int T, n; typedef struct Grid { double x, y; Grid(double a = 0, double b = 0) {x = a, y = b;} } Point, Vector; Vector operator - (Point a, Point b) {return Vector(b.x - a.x, b.y - a.y);} double operator ^ (Vector a, Vector b) {return a.x * b.y - a.y * b.x;}//叉乘 struct Line { Point s, e;// s是重点 Line() {} Line(Point a, Point b) {s = a, e = b;} }; Point p[maxn]; Line L[maxn], que[maxn]; //得到极角角度 double getAngle(Vector a) { return atan2(a.y, a.x); } //得到极角角度 double getAngle(Line a) { return atan2(a.e.y - a.s.y, a.e.x - a.s.x); } //排序:极角小的排前面,极角相同时,最左边的排在最后面,以便去重 bool cmp(Line a, Line b) { Vector va = a.e - a.s, vb = b.e - b.s; double A = getAngle(va), B = getAngle(vb); if (fabs(A - B) < EPS) return ((va) ^ (b.e - a.s)) >= 0; return A < B; } //得到两直线相交的交点 Point getIntersectPoint(Line a, Line b) { double a1 = a.s.y - a.e.y, b1 = a.e.x - a.s.x, c1 = a.s.x * a.e.y - a.e.x * a.s.y; double a2 = b.s.y - b.e.y, b2 = b.e.x - b.s.x, c2 = b.s.x * b.e.y - b.e.x * b.s.y; return Point((c1*b2-c2*b1)/(a2*b1-a1*b2), (a2*c1-a1*c2)/(a1*b2-a2*b1)); } //判断 b,c 的交点是否在 a 的右边 bool onRight(Line a, Line b, Line c) { Point o = getIntersectPoint(b, c); if (((a.e - a.s) ^ (o - a.s)) < 0) return true; return false; } bool HalfPlaneIntersection() { sort(L, L + n, cmp);//排序 int head = 0, tail = 0, cnt = 0;//模拟双端队列 //去重,极角相同时取最后一个。 for (int i = 0; i < n - 1; i++) { if (fabs(getAngle(L[i]) - getAngle(L[i + 1])) < EPS) { continue; } L[cnt++] = L[i]; } L[cnt++] = L[n - 1]; for (int i = 0; i < cnt; i++) { //判断新加入直线产生的影响 while(tail - head > 1 && onRight(L[i], que[tail - 1], que[tail - 2])) tail--; while(tail - head > 1 && onRight(L[i], que[head], que[head + 1])) head++; que[tail++] = L[i]; } //最后判断最先加入的直线和最后的直线的影响 while(tail - head > 1 && onRight(que[head], que[tail - 1], que[tail - 2])) tail--; while(tail - head > 1 && onRight(que[tail - 1], que[head], que[head + 1])) head++; if (tail - head < 3) return false; return true; } //判断输入点的顺序,如果面积 <0,说明输入的点为逆时针,否则为顺时针 bool judge() { double ans = 0; for (int i = 1; i < n - 1; i++) { ans += ((p[i] - p[0]) ^ (p[i + 1] - p[0])); } return ans < 0; } int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = n - 1; i >= 0; i--) { scanf("%lf %lf", &p[i].x, &p[i].y); } if (judge()) {//判断输入顺序,保证逆时针连边。 for (int i = 0; i < n; i++) { L[i] = Line(p[(i + 1)%n], p[i]); } } else { for (int i = 0; i < n; i++) { L[i] = Line(p[i], p[(i + 1)%n]); } } for(int i=0;i<n;i++){ cout<<L[i].s.x<<" "<<L[i].s.y<<"==="<<L[i].e.x<<" "<<L[i].e.y<<endl; } if (HalfPlaneIntersection()) printf("YES\n"); else printf("NO\n"); } return 0; }
半平面交 三角形和长方形交 牛客2019国庆7
//#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps=1e-12; const double EPS=eps; const double pi=acos(-1.0); const double PI=pi; inline double sqr(double x){ return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} }; struct Line{ Point s,e; // s-> 起始点 e->终点 Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x+=(e.x-s.x)*t; res.y+=(e.y-s.y)*t; return res; } }; inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //点积 double get_angle(Point a){ return atan2(a.y,a.x); }// [-PI PI] double get_angle(Line a) { return atan2(a.e.y-a.s.y,a.e.x-a.s.x); } bool judge(Point *pa,int n){ // 用多边形面积来判断正负 double ans = 0; for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); } return ans>=0; } bool cmp(Line a,Line b){ // 极角排序 同极角左边就ok了 Point va=a.e-a.s; double x=get_angle(va); Point vb=b.e-b.s; double y=get_angle(vb); if(fabs(x-y)<eps) { return dcmp(va^(b.e-a.s))>=0; } // 射线的左右 注意和直线区别 else return x<y; } bool onright(Line a,Line b,Line c){ /*Point o=b&c; // 判断 o 是否在a右边 if( ((a.e-o)^(a.s-o))>0 ) return true; return false;*/ Point o = b&c; if (dcmp((a.e - a.s) ^ (o - a.s)) < 0) return true; return false; } const int maxn=50000+100; Point pa[maxn]; Line que[maxn],la[maxn]; double PolygonArea(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针 int n=p.size(); double area=0; for(int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return area/2; // 可改 } double HalfPlaneIntersection(Line *la,int n){ sort(la,la+n,cmp); int head=0,tail=0,cnt=0; // 栈模拟 for (int i=0;i<n-1;i++) { if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) { // 去掉极角相同的(右边边的没用...) continue; }la[cnt++]=la[i]; }la[cnt++]=la[n-1]; for(int i=0;i<cnt;i++){ while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(la[i],que[head],que[head+1])) head++; que[tail++]=la[i]; } while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(que[tail-1],que[head],que[head+1])) head++; if(tail-head<3) return 0.00; // cout<<head<<" "<<tail<<endl; vector<Point> vs; for(int i=head;i<tail-1;i++){vs.push_back(que[i]&que[i+1]);} vs.push_back(que[tail-1]&que[head]); return PolygonArea(vs); } int main(){ double x1,y1,x2,y2; double x3,y3,x4,y4; while(cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4){ int n=0; Point a,b,c,d; a=Point(x1,y1); b=Point(x1,y2); c=Point(x2,y1); vector<Point> vs; vs.push_back(a),vs.push_back(b); vs.push_back(c); if(PolygonArea(vs)>=0) { la[n++]=Line(a,b); la[n++]=Line(b,c); la[n++]=Line(c,a); } else { la[n++]=Line(b,a); la[n++]=Line(a,c); la[n++]=Line(c,b); } a=Point(x3,y3); b=Point(x3,y4); c=Point(x4,y4); d=Point(x4,y3); vs.clear(); vs.push_back(a); vs.push_back(b); vs.push_back(c); vs.push_back(d); if(PolygonArea(vs)>=0) { la[n++]=Line(a,b); la[n++]=Line(b,c); la[n++]=Line(c,d); la[n++]=Line(d,a); } else { la[n++]=Line(b,a); la[n++]=Line(a,d); la[n++]=Line(d,c); la[n++]=Line(c,b); } printf("%.10f\n",HalfPlaneIntersection(la,7)); } }
旋转卡壳
poj 2187 凸包直径(两点间的最远距离) (用int 避免double的误差)
//#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; struct Point{ int x,y; Point(){ x=0,y=0; } Point(int _x,int _y):x(_x),y(_y){} //void output(){ printf("%.2f %.2f\n",x,y); } int operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 int operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} }; struct Line{ Point s,e; int A,B,C; Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 void change(){A=e.y-s.y;B=s.x-e.x;C=e.x*s.y-s.x*e.y; } }; int dis(Point A,Point B) { return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y); } inline int cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //²æ»ý inline int dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //µã»ý bool up(Point a,Point b){ if(a.x!=b.x) return a.x<b.x; return a.y<b.y; } const int maxn=50000+10; vector<Point> vs; Point pa[maxn],pt[maxn]; void tubao(Point *pa,int n){ // 凸包求出来放在vs数组里; 有序(逆时针); sort(pa,pa+n,up); int m=0; for(int i=0;i<n;i++){ while(m>1 && cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } int k=m; for(int i=n-2;i>=0;i--){ while(m>k && cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } if(n>1) m--; for(int i=1;i<=m;i++){ vs.push_back(pt[i]); } } int distance(Point pa,Line la){ la.change(); return abs(la.A*pa.x+la.B*pa.y+la.C);// sqrt(la.A*la.A+la.B*la.B) } int tubao_distance(){ if(vs.size()==0) return 0; if(vs.size()==1) return 0; if(vs.size()==2) return dis(vs[0],vs[1]); int p=0; int n=vs.size(); int ans=0; for(int i=0;i<n;i++){ Line lc=Line(vs[i],vs[(i+1)%n]); while(distance(vs[p],lc)<distance(vs[(p+1)%n],lc)|| distance(vs[p],lc)<distance(vs[((p-1)%n+n)%n],lc)){ p++; p=(p%n+n)%n; } ans=max(ans,dis(vs[i],vs[p])); ans=max(ans,dis(vs[(i+1)%n],vs[p])); } /*p=0; for(int i=0;i<n;i++){ Line lc=Line(vs[i],vs[(i+1)%n]); while(dis(vs[p],vs[i])<dis(vs[(p+1)%n],vs[i])|| dis(vs[p],vs[i])<dis(vs[((p-1)%n+n)%n],vs[i])){ p++; p=(p%n+n)%n; } ans=max(ans,dis(vs[i],vs[p])); //ans=max(ans,dis(vs[(i+1)%n],vs[p])); }*/ return ans; } int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d %d",&pa[i].x,&pa[i].y); } tubao(pa,n); int ans=tubao_distance(); printf("%d\n",ans); }
poj 2451 半平面交面积
//#include<bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps=1e-12; const double EPS=eps; const double pi=acos(-1.0); const double PI=pi; inline double sqr(double x){ return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} }; struct Line{ Point s,e; // s-> 起始点 e->终点 Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x+=(e.x-s.x)*t; res.y+=(e.y-s.y)*t; return res; } }; inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //点积 double get_angle(Point a){ return atan2(a.y,a.x); }// [-PI PI] double get_angle(Line a) { return atan2(a.e.y-a.s.y,a.e.x-a.s.x); } bool judge(Point *pa,int n){ // 用多边形面积来判断正负 double ans = 0; for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); } return ans>=0; } bool cmp(Line a,Line b){ // 极角排序 同极角左边就ok了 Point va=a.e-a.s; double x=get_angle(va); Point vb=b.e-b.s; double y=get_angle(vb); if(fabs(x-y)<eps) { return dcmp(va^(b.e-a.s))>=0; } // 射线的左右 注意和直线区别 else return x<y; } bool onright(Line a,Line b,Line c){ /*Point o=b&c; // 判断 o 是否在a右边 if( ((a.e-o)^(a.s-o))>0 ) return true; return false;*/ Point o = b&c; if (dcmp((a.e - a.s) ^ (o - a.s)) < 0) rQeturn true; return false; } const int maxn=50000+100; Point pa[maxn]; Line que[maxn],la[maxn]; double PolygonArea(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针 int n=p.size(); double area=0; for(int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return fabs(area/2); // 可改 } double HalfPlaneIntersection(Line *la,int n){ sort(la,la+n,cmp); int head=0,tail=0,cnt=0; // 栈模拟 for (int i=0;i<n-1;i++) { if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) { // 去掉极角相同的(右边边的没用...) continue; }la[cnt++]=la[i]; }la[cnt++]=la[n-1]; for(int i=0;i<cnt;i++){ while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(la[i],que[head],que[head+1])) head++; que[tail++]=la[i]; } while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--; while(tail-head>1 && onright(que[tail-1],que[head],que[head+1])) head++; if(tail-head<3) return 0.00; vector<Point> vs; for(int i=head;i<tail-1;i++){vs.push_back(que[i]&que[i+1]);} vs.push_back(que[tail-1]&que[head]); return PolygonArea(vs); } int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%lf %lf %lf %lf",&la[i].s.x,&la[i].s.y,&la[i].e.x,&la[i].e.y); } double lim=10000; la[n++]=Line(Point(0,0),Point(lim,0)); la[n++]=Line(Point(lim,0),Point(lim,lim)); la[n++]=Line(Point(lim,lim),Point(0,lim)); la[n++]=Line(Point(0,lim),Point(0,0)); printf("%.1f\n",HalfPlaneIntersection(la,n)); return 0; }