BZOJ 2618: [Cqoi2006]凸多边形 半平面交

xiaoxiao2021-02-28  55

2618: [Cqoi2006]凸多边形

Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2141  Solved: 1051[Submit][Status][Discuss]

Description

逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:

则相交部分的面积为5.233。

Input

第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

 

Output

    输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

 

Sample Input

26-2 0-1 -21 -22 01 2-1 240 -31 -12 2-1 0

Sample Output

5.233

HINT

100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

bzoj的板子题

#include<cmath> #include<ctime> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<iomanip> #include<vector> #include<string> #include<bitset> #include<queue> #include<set> #include<map> using namespace std; typedef double db; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f; } void print(int x) {if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x+'0');} const int N=510; const db eps=1e-8; struct point { db x,y; friend point operator +(const point &a,const point &b) {return (point){a.x+b.x,a.y+b.y};} friend point operator -(const point &a,const point &b) {return (point){a.x-b.x,a.y-b.y};} friend db dis(const point &a,const point &b) { point tmp(a-b); return sqrt(tmp.x*tmp.x+tmp.y*tmp.y); } friend db cross(const point &x,const point &y,const point &bas) { point a(x-bas),b(y-bas); return a.x*b.y-a.y*b.x; } }p[N],st[N]; struct segment { point X,Y;db angle; friend bool operator <(const segment &a,const segment &b) { if(abs(a.angle-b.angle)<eps) return cross(a.Y,b.X,a.X)<0; return a.angle<b.angle; } friend point get_insert(const segment &a,const segment &b) { db S[2]; point res; S[0]=cross(a.X,a.Y,b.X), S[1]=cross(a.Y,a.X,b.Y); res.x=(b.X.x*S[1]+b.Y.x*S[0])/(S[0]+S[1]), res.y=(b.X.y*S[1]+b.Y.y*S[0])/(S[0]+S[1]); return res; } }seg[N]; int seg_cnt; inline void add_seg(const point &a,const point &b) { seg[++seg_cnt].X=a,seg[seg_cnt].Y=b; seg[seg_cnt].angle=atan2(b.y-a.y,b.x-a.x); } bool check(int a,int b,int c) { point tmp(get_insert(seg[a],seg[b])); return cross(seg[c].Y,tmp,seg[c].X)<0; } int q[N],top; void hpi() { register int i,head(0),tail(2),tot(1); sort(seg+1,seg+1+seg_cnt); for(i=2;i<=seg_cnt;++i) if(seg[i].angle-seg[tot].angle>eps) seg[++tot]=seg[i]; q[0]=1,q[1]=2; for(i=3;i<=tot;++i) { while(head<tail-1 && check(q[tail-1],q[tail-2],i)) tail--; while(head<tail-1 && check(q[head],q[head+1],i)) head++; q[tail++]=i; } while(head<tail-1 && check(q[tail-1],q[tail-2],q[head])) tail--; while(head<tail-1 && check(q[head],q[head+1],q[tail-1])) head++; if(tail-head>=3) q[tail++]=q[head]; for(i=head;i<tail-1;++i) st[++top]=get_insert(seg[q[i]],seg[q[i+1]]); } void solve() { db S(0); register int i; for(i=2;i<top;++i) S+=cross(st[i],st[i+1],st[1]); printf("%.3lf\n",S*0.5); } int main() { register int T=read(),n,i; while(T--) { n=read(); for(i=1;i<=n;++i) p[i].x=read(),p[i].y=read(); p[n+1]=p[1]; for(i=1;i<=n;++i) add_seg(p[i],p[i+1]); } hpi(); solve(); return 0; }
转载请注明原文地址: https://www.6miu.com/read-2619287.html

最新回复(0)