NKOJ 2003 (CQOI 2006)凸多邊形(半平面交)

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]內的整數


向量表示直線,做暴力半平面交,複雜度O(n2) ,保存模板。


代碼:

#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());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章