【半平面交模板】bzoj2618 [Cqoi2006]凸多邊形
阿新 • • 發佈:2018-12-11
理解好求兩直線交點的公式
單調佇列最後用 隊尾彈隊首 隊首彈隊尾
#include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; const int N=500+5; const double eps=1e-8; int dcmp(double x) {if(fabs(x)<=eps) return 0; if(x>0) return 1; return -1; } int n,head,tail,m,cnt; double ans; struct point {double x,y; point operator + (point r) const{point t; t.x=x+r.x; t.y=y+r.y; return t;} point operator - (point r) const{point t; t.x=x-r.x; t.y=y-r.y; return t;} double operator * (point r) const{return x*r.y-y*r.x;} point operator * (double r)const{point t; t.x=x*r; t.y=y*r; return t;} }b[N]; struct line {point p1,p2; double th; bool operator <(line b) const {if(dcmp(th-b.th)==0) return dcmp((p2-p1)*(b.p2-p1))<0; return dcmp(th-b.th)<0; } }a[N],q[N]; inline point get(line a,line b) {point va=a.p2-a.p1, vb=b.p2-b.p1, u=b.p1-a.p1; point re=b.p1+vb*((u*va)/(va*vb)); return re; } inline bool judge(line a,line b,line k) {point p=get(a,b); return dcmp((k.p2-k.p1)*(p-k.p1))<0; } inline void half() {sort(a+1,a+m+1); for(int i=1;i<=m;i++) if(dcmp(a[i].th-a[i-1].th)!=0) a[++cnt]=a[i]; head=1; tail=0; q[++tail]=a[1]; q[++tail]=a[2]; for(int i=3;i<=cnt;i++) {while(head<tail && judge(q[tail-1],q[tail],a[i])) tail--; while(head<tail && judge(q[head+1],q[head],a[i])) head++; q[++tail]=a[i]; } while(head<tail && judge(q[tail-1],q[tail],q[head])) tail--; while(head<tail && judge(q[head+1],q[head],q[tail])) head++; q[tail+1]=q[head]; for(int i=head;i<=tail;i++) b[++n]=get(q[i],q[i+1]); } int main() { int num,k; scanf("%d",&k); while(k--) {scanf("%d",&num); for(int i=1;i<=num;i++) scanf("%lf%lf",&b[i].x,&b[i].y); b[num+1]=b[1]; for(int i=1;i<=num;i++) a[++m].p1=b[i],a[m].p2=b[i+1]; } for(int i=1;i<=m;i++) a[i].th=atan2(a[i].p2.y-a[i].p1.y,a[i].p2.x-a[i].p1.x); half(); b[n+1]=b[1]; for(int i=1;i<=n;i++) ans+=b[i]*b[i+1]; ans=fabs(ans)/2.0; printf("%.3lf",ans); return 0; }