[BZOJ 2618][CQOI 2006]凸多边形(半平面交+三角剖分求多边形面积)

来源:互联网 发布:速卖通数据分析工具 编辑:程序博客网 时间:2024/06/03 17:19

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=2618

思路

实际上就是很多条直线求半平面交的面积,这是很显然的。
所以直接用半平面交+三角剖分模板就能水过。

代码

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <cmath>#define MAXN 10000#define EPS 1e-6using namespace std;int dcmp(double a){    if(fabs(a)<EPS) return 0;    if(a>EPS) return 1;    return -1;}struct Point{    double x,y;    Point(){}    Point(double _x,double _y):x(_x),y(_y){}}points[MAXN],polygon[MAXN];int n=0,sizeOfPoly=0;Point operator-(Point a,Point b){    return Point(a.x-b.x,a.y-b.y);}Point operator+(Point a,Point b){    return Point(a.x+b.x,a.y+b.y);}Point operator*(Point a,double b){    return Point(a.x*b,a.y*b);}Point operator/(Point a,double b){    return Point(a.x/b,a.y/b);}double operator*(Point a,Point b){    return a.x*b.x+a.y*b.y;}double cross(Point a,Point b){    return a.x*b.y-a.y*b.x;}struct Line{    Point st,ed;    double ang;    Line(){}    Line(Point _st,Point _ed):st(_st),ed(_ed)    {        ang=atan2((st-ed).y,(st-ed).x);    }}lines[MAXN],q[MAXN];int top=0,h=1,t=0;Point getLineIntersec(Line a,Line b){    double x=cross(a.ed-a.st,b.ed-b.st); //!!!!!    double y=cross(b.st-a.st,a.ed-a.st);    return b.st+(b.ed-b.st)*y/x;}bool cmp(Line a,Line b) //按照极角升序排序{    if(!dcmp(a.ang-b.ang)) return dcmp(cross(a.ed-a.st,b.ed-a.st))>0;    return dcmp(a.ang-b.ang)<0;}bool onLeft(Line a,Point b){    return dcmp(cross(b-a.st,a.ed-a.st))<=0;}void HalfPanelIntersec() //半平面交{    int tot=0;    sort(lines+1,lines+n+1,cmp);    for(int i=1;i<=n;i++) //去掉极角相同的直线    {        if(dcmp(lines[i].ang-lines[i-1].ang)) tot++;        lines[tot]=lines[i];    }    q[++t]=lines[1],q[++t]=lines[2];    for(int i=1;i<=tot;i++)    {        while(h<t&&!onLeft(lines[i],getLineIntersec(q[t-1],q[t]))) t--;        if(h<t&&!dcmp(fabs(cross(q[t].ed-q[t].st,q[t-1].ed-q[t-1].st))))        {            if(onLeft(q[t],lines[i].st)) //i与队尾直线平行且方向相同,则需要保留靠近半平面交内部的那条                q[t]=lines[i];        }        else q[++t]=lines[i];    }    while(t-h>=2&&!onLeft(q[t],getLineIntersec(q[h],q[h+1]))) h++;    while(t-h>=2&&!onLeft(q[h],getLineIntersec(q[t],q[t-1]))) t--;    for(int i=h;i<t;i++)        polygon[++sizeOfPoly]=getLineIntersec(q[i],q[i+1]);    polygon[++sizeOfPoly]=getLineIntersec(q[t],q[h]);}double getSqrOfPolygon(){    double sqr=0;    if(sizeOfPoly<=2) return 0;    polygon[++sizeOfPoly]=polygon[1];    for(int i=1;i<=sizeOfPoly;i++)        sqr+=cross(polygon[i],polygon[i+1]);    return fabs(sqr)/2;}int main(){    int m;    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        int cnt=0;        scanf("%d",&cnt);        Point p1,p2,tmp;        scanf("%lf%lf",&p1.x,&p1.y);        tmp=p1;        for(int j=2;j<=cnt;j++)        {            scanf("%lf%lf",&p2.x,&p2.y);            lines[++n]=Line(p1,p2);            p1=p2;        }        lines[++n]=Line(p1,tmp);    }    HalfPanelIntersec();    printf("%.3lf\n",getSqrOfPolygon());    return 0;}
0 0
原创粉丝点击