P2003【CQOI2006】凸多邊形
問題描述
逆時針給出n個凸多邊形的頂點座標,求它們交的面積。例如n=2時,兩個凸多邊形如下圖:
則相交部分的面積爲5.233。
輸入格式
第一行有一個整數n,表示凸多邊形的個數,以下依次描述各個多邊形。第i個多邊形的第一行包含一個整數mi,表示多邊形的邊數,以下mi行每行兩個整數,逆時針給出各個頂點的座標。
輸出格式
僅包含一個實數,表示相交部分的面積,保留三位小數。
樣例輸入
2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
樣例輸出
5.233
提示
50%的數據滿足:n=2
100%的數據滿足:2<=n<=10,3<=mi<=50,每維座標爲[-1000,1000]內的整數
向量表示直線,做暴力半平面交,複雜度 ,保存模板。
代碼:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 2005
using namespace std;
const double eps=1e-9;
struct node
{
double x,y;
double operator*(const node &b)const
{return x*b.y-y*b.x;}
node operator+(const node &b)const
{return (node){x+b.x,y+b.y};}
node operator-(const node &b)const
{return (node){x-b.x,y-b.y};}
node operator*(const double b)const
{return (node){b*x,b*y};}
}A[15][N],S[N],T[N];
struct nodd{node p,v;}Line[N];
int n,m,top;
node Intersection(nodd a,nodd b)
{
double k=((a.p-b.p)*a.v)/(b.v*a.v);
return b.p+b.v*k;
}
void Cut(nodd D)
{
int i,j,k=0;
S[0]=S[top];
S[top+1]=S[1];
for(i=1;i<=top;i++)
{
if(D.v*(S[i]-D.p)<-eps)
{
if(D.v*(S[i-1]-D.p)>-eps)T[++k]=Intersection(D,nodd{S[i-1],S[i]-S[i-1]});
if(D.v*(S[i+1]-D.p)>-eps)T[++k]=Intersection(D,nodd{S[i],S[i+1]-S[i]});
}
else T[++k]=S[i];
}
copy(T+1,T+k+1,S+1);top=k;
}
double Garea()
{
int i,j,k=0;
S[top+1]=S[1];
double ans=0;
for(i=1;i<=top;i++)ans+=S[i]*S[i+1];
return ans;
}
int main()
{
int i,j,k;double x,y,z;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&k);
for(j=1;j<=k;j++)scanf("%lf%lf",&A[i][j].x,&A[i][j].y);
for(j=1;j<=k;j++)Line[++m]=(nodd){A[i][j],A[i][j%k+1]-A[i][j]};
}
S[++top]=(node){-1e5,1e5};
S[++top]=(node){-1e5,-1e5};
S[++top]=(node){1e5,-1e5};
S[++top]=(node){1e5,1e5};
for(i=1;i<=m;i++)Cut(Line[i]);
printf("%.3lf",0.5*Garea());
}