2618: [Cqoi2006]凸多边形
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 656 Solved: 340
[Submit][Status][Discuss]
Description
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
则相交部分的面积为5.233。
Input
第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
Output
输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。
Sample Input
2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
Sample Output
5.233
HINT
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
Source
【思路】
半平面交即若干个直线代表的半平面的重合部分。
【代码】
1 #include<cmath> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 8 const int eps = 1e-10; 9 10 struct Pt { 11 double x,y; 12 Pt (double x=0,double y=0) :x(x),y(y) {} 13 }; 14 typedef Pt vec; 15 16 vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); } 17 vec operator + (vec a,vec b) { return vec(a.x+b.x,a.y+b.y); } 18 vec operator * (vec a,double x) { return vec(a.x*x,a.y*x); } 19 20 double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; } 21 22 struct Line { 23 Pt p; vec v; double ang; 24 Line() {} 25 Line(Pt p,vec v) :p(p),v(v) { ang=atan2(v.y,v.x); } 26 bool operator < (const Line& rhs) const { 27 return ang < rhs.ang; 28 } 29 }; 30 bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>0; } 31 Pt getLineInter(Line a,Line b) { 32 vec u=a.p-b.p; 33 double t=cross(b.v,u)/cross(a.v,b.v); 34 return a.p+a.v*t; 35 } 36 vector<Pt> HPI(vector<Line> L) { 37 int n=L.size(); 38 sort(L.begin(),L.end()); 39 int f,r; 40 vector<Pt> p(n) , ans; 41 vector<Line> q(n); 42 q[f=r=0]=L[0]; 43 for(int i=1;i<n;i++) { 44 while(f<r && !onleft(L[i],p[r-1])) r--; 45 while(f<r && !onleft(L[i],p[f])) f++; 46 q[++r]=L[i]; 47 if(fabs(cross(q[r].v,q[r-1].v))<eps) { 48 r--; 49 if(onleft(q[r],L[i].p)) q[r]=L[i]; 50 } 51 if(f<r) p[r-1]=getLineInter(q[r-1],q[r]); 52 } 53 while(f<r && !onleft(q[f],p[r-1])) r--; 54 if(r-f<=1) return ans; 55 p[r]=getLineInter(q[r],q[f]); 56 for(int i=f;i<=r;i++) ans.push_back(p[i]); 57 return ans; 58 } 59 vector<Line> L; 60 vector<Pt> p; 61 Pt t[55]; 62 int n,m; 63 64 int main() { 65 scanf("%d",&n); 66 for(int i=0;i<n;i++) { 67 scanf("%d",&m); 68 for(int i=0;i<m;i++) 69 scanf("%lf%lf",&t[i].x,&t[i].y); 70 for(int i=1;i<m;i++) 71 L.push_back(Line(t[i-1],t[i]-t[i-1])); 72 L.push_back(Line(t[m-1],t[0]-t[m-1])); 73 } 74 p = HPI(L); 75 double ans=0.0; int m=p.size(); 76 for(int i=1;i<m-1;i++) 77 ans += cross(p[i]-p[0],p[i+1]-p[0]); 78 printf("%.3lf",ans/2); 79 return 0; 80 }