2618: [Cqoi2006]凸多边形
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1011 Solved: 515
[ 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
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E3;
typedef double DB;
const DB eps = 1E-10;
const DB two = 2.00;
struct Point{
DB x,y;
Point(){}
Point(DB x,DB y): x(x),y(y){}
Point operator - (const Point &b) {return Point(x - b.x,y - b.y);}
Point operator * (const DB &b) {return Point(x*b,y*b);}
Point operator + (const Point &b) {return Point(x + b.x,y + b.y);}
}poi[maxn],sec[maxn];
typedef Point Vector;
struct Line{
Point p; Vector v; DB ang;
Line(){}
Line(Point p,Vector v): p(p),v(v){ang = atan2(v.y,v.x);}
bool operator < (const Line &b) const {return ang < b.ang;}
}line[maxn],Q[maxn];
int n,m,head,tail,cnt;
DB Cross(Vector v1,Vector v2) {return v1.x*v2.y - v2.x*v1.y;}
bool Onleft(Line k,Point po) {return Cross(k.v,po - k.p) > 0;}
Point GetIntersection(Line l1,Line l2)
{
Vector u = l1.p - l2.p;
DB t = Cross(u,l2.v)/Cross(l2.v,l1.v);
return l1.p + l1.v*t;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
while (n--) {
scanf("%d",&m);
for (int i = 1; i <= m; i++) {
DB x,y; scanf("%lf%lf",&x,&y);
poi[i] = Point(x,y);
}
poi[++m] = poi[1];
for (int i = 2; i <= m; i++)
line[cnt++] = Line(poi[i-1],poi[i] - poi[i-1]);
}
sort(line,line + cnt);
Q[head = tail = 0] = line[0];
for (int i = 1; i < cnt; i++) {
while (head < tail && !Onleft(line[i],sec[tail-1])) --tail;
while (head < tail && !Onleft(line[i],sec[head])) ++head;
Q[++tail] = line[i];
if (fabs(Cross(Q[tail].v,Q[tail-1].v)) < eps) {
--tail;
if (Onleft(Q[tail],line[i].p)) Q[tail] = line[i];
}
if (head < tail) sec[tail-1] = GetIntersection(Q[tail],Q[tail-1]);
}
while (head < tail && !Onleft(Q[head],sec[tail-1])) --tail;
sec[tail] = GetIntersection(Q[head],Q[tail]); sec[tail+1] = sec[head];
DB Ans = 0; Point o = Point(233.233,322.322);
for (int i = head; i <= tail; i++) Ans += Cross(sec[i],sec[i+1]);
printf("%.3lf",Ans/two);
return 0;
}