第十二届湖南省赛:三角形和矩形

来源:互联网 发布:inside剧情解析 知乎 编辑:程序博客网 时间:2024/05/21 15:00

Bobo 有一个三角形和一个矩形,他想求他们交的面积。
具体地,三角形和矩形由 8 个整数 x 1,y 1,x 2,y 2,x 3,y 3,x 4,y 4 描述。 表示三角形的顶点坐标是 (x 1,y 1),(x 1,y 2),(x 2,y 1), 矩形的顶点坐标是 (x 3,y 3),(x 3,y 4),(x 4,y4),(x 4,y 3).
Input
输入包含不超过 30000 组数据。
每组数据的第一行包含 4 个整数 x 1,y 1,x 2,y 2 (x 1≠x 2,y 1≠y 2).
第二行包含 4 个整数 x 3,y 3,x 4,y 4 (x 3<x 4,y 3<y 4).
(0≤x i,y i≤10 4)
Output
对于每组数据,输出一个实数表示交的面积。绝对误差或相对误差小于 10 -6 即认为正确。
Sample Input
1 1 3 30 0 2 20 3 3 10 0 2 24462 1420 2060 29694159 257 8787 2970
Sample Output
1.000000000.75000000439744.13967527

思路:用半平面交模版即可。注意初始向量的方向。

#include<cstring>#include<algorithm>#include<cmath>#include<cstdio>#include<vector>#include<iostream>using namespace std;struct Point{    double x,y;}tri[4],rec[5],ch[10];struct Line{    Point p;       //直线上任意一点    Point v;      //直线方向向量    double angle;  //极角    Line(){}    Line(Point p,Point v):p(p),v(v){angle=atan2(v.y,v.x);}    bool operator<(const Line& L)const{return angle<L.angle;}}L[10];Point Vector(Point a,Point b)     //求向量a-b{Point c;c.x=a.x-b.x;c.y=a.y-b.y;return c;}double cross(Point a,Point b)       //叉积{return (a.x*b.y-a.y*b.x);}bool Onleft(Line L,Point p){return cross(L.v,Vector(p,L.p))>0;}  //点P在有向直线L的左边(线上不算)Point Getinter(Line a,Line b){    Point u=Vector(a.p,b.p);    double t=cross(b.v,u)/cross(a.v,b.v);    return (Point){a.p.x+a.v.x*t,a.p.y+a.v.y*t};}int Half(Line *L,int n,Point *poly){    sort(L,L+n);    int first,last;    Point *p=new Point[n];    Line *q=new Line[n];    q[first=last=0]=L[0];    for(int i=1;i<n;i++)    {        while(first<last&&!Onleft(L[i],p[last-1]))last--;        while(first<last&&!Onleft(L[i],p[first]))first++;        q[++last]=L[i];        if(fabs(cross(q[last].v,q[last-1].v))<1e-7)        {            last--;            if(Onleft(q[last],L[i].p))q[last]=L[i];        }        if(first<last)p[last-1]=Getinter(q[last-1],q[last]);    }    while(first<last&&!Onleft(q[first],p[last-1]))last--;  //删除无用面    if(last-first<=1)return 0;      //空集    p[last]=Getinter(q[last],q[first]);    int m=0;    for(int i=first;i<=last;i++)poly[m++]=p[i];    return m;}double Polyarea(Point *p,int n)   //求多边形面积(任意形状都可){double area=0;for(int i=1;i<n-1;i++){area+=cross(Vector(p[i],p[0]),Vector(p[i+1],p[0]));}return area/2;}int cmp1(const Point &x,const Point& y){    if(x.x==y.x)return x.y<y.y;    return x.x<y.x;}int cmp2(const Point &x,const Point& y){    if(x.x==y.x)return x.y>y.y;    return x.x<y.x;}int main(){    double x1,y1,x2,y2,x3,y3,x4,y4;    while(scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2)!=EOF)    {        tri[0].x=x1,tri[0].y=y1;        tri[1].x=x1,tri[1].y=y2;        tri[2].x=x2,tri[2].y=y1;        if(x2>x1)sort(tri,tri+3,cmp2);        else sort(tri,tri+3,cmp1);         //让点按逆时针排序        scanf("%lf%lf%lf%lf",&x3,&y3,&x4,&y4);        rec[0].x=x3,rec[0].y=y3;        rec[1].x=x4,rec[1].y=y3;        rec[2].x=x4,rec[2].y=y4;        rec[3].x=x3,rec[3].y=y4;        int n=0;        for(int i=0;i<3;i++)L[n++]=Line(tri[i],Vector(tri[(i+1)%3],tri[i]));        for(int i=0;i<4;i++)L[n++]=Line(rec[i],Vector(rec[(i+1)%4],rec[i]));        int m=Half(L,n,ch);        printf("%0.8lf\n",Polyarea(ch,m));    }    return 0;}



阅读全文
1 0