山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 2618 2618: [Cqoi2006]凸多边形(半平面交)

 

2618: [Cqoi2006]凸多边形

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

5.233

HINT

100%的数据满足:2<=n<=103<=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 }
View Code

 

posted on 2016-02-06 12:50  hahalidaxin  阅读(273)  评论(0编辑  收藏  举报