• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
magicat
博客园    首页    新随笔    联系   管理    订阅  订阅
[CQOI2006]凸多边形 /【模板】半平面交

是半平面交模板题

逆时针给出 n 个凸多边形的顶点坐标,求它们交的面积。

例如 n=2 时,两个凸多边形如下图:

1.jpg

则相交部分的面积为 5.233。

输入格式

第一行有一个整数 n,表示凸多边形的个数,以下依次描述各个多边形。

第 i 个多边形的第一行包含一个整数 mi,表示多边形的边数,以下 mi 行每行两个整数,逆时针给出各个顶点的坐标。

#include<iostream>
#include<cmath>
#include<math.h>
#include<algorithm>

using namespace std;

#define x first 
#define y second 
using namespace std;

typedef pair<double,double>PDD;
const int N=510;
const double eps = 1e-8;

int cnt=0;
struct Line
{
    PDD st,ed;
}line[N];
PDD pg[N],ans[N];
int q[N];

int sign(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return 0;
    return 1;
}
int dcmp(double x,double y)
{
    if(fabs(x-y)<eps)   return 0;
    if(x<y) return -1;
    return 1;
}

double getangle(const Line& a)
{
    return atan2(a.ed.y-a.st.y,a.ed.x-a.st.x); 
} 

PDD operator - (PDD a,PDD b)
{
    return {a.x-b.x,a.y-b.y};
}

double cross(PDD a,PDD b)
{
    return a.x*b.y-a.y*b.x;
}

double area(PDD a,PDD b,PDD c)
{
    return cross(b-a,c-a);
}

bool cmp(const Line& a,const Line& b)
{
    double A=getangle(a),B=getangle(b);
    if(!dcmp(A,B))  return area(a.st,a.ed,b.ed)<0;
    return A<B;
}

PDD getlineintersection(PDD p,PDD v,PDD q,PDD w)
{
    auto u=p-q;
    double t=cross(w,u)/cross(v,w);
    return {p.x+v.x*t,p.y+v.y*t};
}

PDD getlineintersection(Line a,Line b)
{
    return getlineintersection(a.st,a.ed-a.st,b.st,b.ed-b.st);
}

bool onright(Line& a,Line& b,Line& c)
{
    auto o=getlineintersection(b,c);
    return sign(area(a.st,a.ed,o))<=0;
}

double halfplaneintersection()
{
    sort(line,line+cnt,cmp);
    int hh=0,tt=-1;
    for(int i=0;i<cnt;i++)
    {
        if(i&&!dcmp(getangle(line[i]),getangle(line[i-1]))) continue;
        while (hh+1<=tt&&onright(line[i],line[q[tt - 1]],line[q[tt]]))  tt--;
        while (hh+1<=tt&&onright(line[i],line[q[hh]],line[q[hh + 1]]))  hh++;
        q[++tt]=i;
    }
    while(hh+1<=tt&&onright(line[q[hh]],line[q[tt-1]],line[q[tt]])) tt--;
    while(hh+1<=tt&&onright(line[q[tt]],line[q[hh]],line[q[hh+1]])) hh++;
    q[++tt]=q[hh];
    int k=0;
    for(int i=hh;i<tt;i++)
    {
        ans[k++]=getlineintersection(line[q[i]],line[q[i+1]]);
    }
    double res=0;
    for(int i=1;i+1<k;i++)
    {
        res+=area(ans[0],ans[i],ans[i+1]);
    }
    return res/2;
}



int main()
{
    int n,m;
    cin>>n;
    while(n--)
    {
        cin>>m;
        for(int i=0;i<m;i++)
        {
            cin>>pg[i].x>>pg[i].y;
        }

        for(int i=0;i<m;i++)
        {
            line[cnt++] = {pg[i],pg[(i+1)%m]};
        }
    }
    double res=halfplaneintersection();
    printf("%.3lf\n",res);
    return 0;
}

 

本文来自博客园,作者:magicat,转载请注明原文链接:https://www.cnblogs.com/magicat/p/15559073.html

posted on 2021-11-15 23:14  magicat  阅读(46)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3